C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: SqlDataAdapterのUpdateコマンドエラー?


(過去ログ 124 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■73954 / inTopicNo.1)  SqlDataAdapterのUpdateコマンドエラー?
  
□投稿者/ しろくま5 (1回)-(2014/11/17(Mon) 17:29:26)

分類:[VB.NET/VB2005 以降] 

はじめて投稿致します。
現在、会社のシステム関係のプログラミングをVS2013 for Desktop環境にてVBを使い行っております。

現在DBとの接続をSqlDataAdapterを使って行っているのですが、その中でupdateがうまくいかず困っております。

状況としましては、INSERTをUpdateで行いたくソースを書いているのですが、他のDBの情報をSELECTしてきたDataTableを使い
Updateを行うと、正しく追加されません。ですが、エラーも表示されないといった状況となっております。

ソースに間違っている箇所が見当たらず、試しにDataTableを自分で生成し、同じカラム名、カラム数にし複数レコードを登録した
DataTableを使いUpdateしたところ、正しく登録されました。


adapter.Update( DataTable )

上のDataTable部分を変えてるだけで他のソースは同一の物となっております。


わかりづらいかと思いますが、よろしくお願いします。
引用返信 編集キー/
■73955 / inTopicNo.2)  Re[1]: SqlDataAdapterのUpdateコマンドエラー?
□投稿者/ 魔界の仮面弁士 (171回)-(2014/11/17(Mon) 17:49:10)
2014/11/17(Mon) 17:54:16 編集(投稿者)

No73954 (しろくま5 さん) に返信
> INSERTをUpdateで行いたく
INSERT (の SQL 文) を、(SqlDataAdapter の) Update メソッド経由で呼び出すということですね?


> 他のDBの情報をSELECTしてきたDataTableを使い
SELECT 直後は、各行の RowState は Unchanged ですよね。
InsertCommand に回したいのであれば、別の DataTable に取り込み直すか
.SetAdded() を呼ぶなどして、RowState を Added にしておく必要が
ありますが、その点は大丈夫でしょうか?


> Updateを行うと、正しく追加されません。
下記の事例に該当していたりはしませんか?
http://www.atmarkit.co.jp/fdotnet/dotnettips/532dbfilecopy/dbfilecopy.html


> 試しにDataTableを自分で生成し、同じカラム名、カラム数にし複数レコードを登録した
> DataTableを使いUpdateしたところ、正しく登録されました。
上記 2 点いずれも該当しないようであれば、現在の
具体的なデータ構造などの情報を公開することはできますか?
引用返信 編集キー/
■73956 / inTopicNo.3)  Re[2]: SqlDataAdapterのUpdateコマンドエラー?
□投稿者/ しろくま5 (2回)-(2014/11/17(Mon) 18:15:54)
返信ありがとうございます。

No73955 (魔界の仮面弁士 さん) に返信
> ■No73954 (しろくま5 さん) に返信
>>INSERTをUpdateで行いたく
> INSERT (の SQL 文) を、(SqlDataAdapter の) Update メソッド経由で呼び出すということですね?

はい、そのようになります。


>>ソースを書いているのですが、他のDBの情報をSELECTしてきたDataTableを使い
>>Updateを行うと、正しく追加されません。
> 下記の事例に該当していたりはしませんか?
> http://www.atmarkit.co.jp/fdotnet/dotnettips/532dbfilecopy/dbfilecopy.html

DBへのアクセスはVS内では何も行っておらず、SQL ServerManagement2008を使って行っております。


>>試しにDataTableを自分で生成し、同じカラム名、カラム数にし複数レコードを登録した
>>DataTableを使いUpdateしたところ、正しく登録されました。
> それらの具体的な情報を公開することはできますか?

ライブラリ化などしており、ソース全部そのままでは出せなかったので大まかな流れですが
Adapterへの接続はSELECTとINSERTで分けており、SELECTのあと閉じてます。
そのあとでINSERT用のAdapterを生成し、パラメータを追加し、最終的にDataTableを渡してUpdateメソッドを実行といった流れです。

strConnect = strServer & strUserID & strPassword & strDatabase & dbName

adp = New SqlDataAdapter
connect = New SqlConnection(strConnect)
connect.Open()

adp.SelectCommand = New SqlCommand("select test1, test2 from TESTDB2", connect)
dim ds as new DataSet
adp.fill(ds)
dim dt as DataTable = ds.tables(0)
connect.close()

connect.Open()
adp.InsertCommand = New SqlCommand("INSERT INTO TESTDB1(COL1, COL2) VALUES(@COL1, @COL2)", connect)
adp.InsertCommand.Parameters.Add("@COL1", SqlDbType.NVarChar, 20, "test1")
adp.InsertCommand.Parameters.Add("@COL2", SqlDbType.NVarChar, 20, "test2")

Dim table As New DataTable
table.Columns.Add("test1")
table.Columns.Add("test2")
For i As Integer = 1 To 10
Dim row As DataRow = table.NewRow
row("test1") = "COL1 = " & i
row("test2") = "COL2 = " & i
table.Rows.Add(row)
Next

    adp.Update(table) → 正常に登録
adp.Update(dt) → 登録されない


最後のUpdateについてはどちらか片方しか行っておりません。
引用返信 編集キー/
■73958 / inTopicNo.4)  Re[3]: SqlDataAdapterのUpdateコマンドエラー?
□投稿者/ 魔界の仮面弁士 (172回)-(2014/11/17(Mon) 18:53:26)
No73956 (しろくま5 さん) に返信
> dim ds as new DataSet
> adp.fill(ds)
> dim dt as DataTable = ds.tables(0)
> connect.close()

これだけでは不十分だったりします。

No73956 にて、DataRow の RowState プロパティについて触れていますが、
このプロパティのことはご存知でしょうか?

---------
SelectCommand で取得したばかりの未加工のデータは、
DataRow の RowState プロパティが「Unchanged」の状態です。

そしてその行を編集すると、RowState が「Modified」へと変化します。
編集前の値と編集後の値を取り出すことも出来ます。

 Dim row As DataRow = ds.tables(0).Rows(0)
 oldValue = row("列名", DataRowVersion.Original)
 newValue = row("列名", DataRowVersion.Current)


そして、「削除」した場合は DataTable.Rows から取り除かれるのではなく、
「Deleted」状態となります。いわゆる削除フラグが立てられた状態です。
このモードの時は、
 oldValue = row("列名", DataRowVersion.Original) '削除する前の値
 'newValue = row("列名", DataRowVersion.Current) '削除済みの行なのでエラー!
という動作になります。


そして追加した行については、「Added」状態です。
.Rows.Add で追加した場合などがこの状態ですね。
---------

Update メソッドに DataTable を引き渡した場合、
各行の RowState プロパティが参照され、各コマンドに引き渡されます。

 "Modified" な行は UpdateCommand 経由で UPDATE の SQL へ
 "Deleted" な行は DeleteCommand 経由で DELETE の SQL へ
 "Added" な行は InsertCommand 経由で INSERT INTO の SQL へ

という感じです。Unchanged な行は編集の必要が無いので無視されます。


今回の場合、
 adp.fill(ds)
 dim dt as DataTable = ds.tables(0)
は、全ての行が Unchanged なので無視され、
 table.Rows.Add(row)
は、Added がマークされているため、登録されたわけです。
-----------

なお、Update メソッドを呼び出した後も、RowState を変更せずにおくと、
再度 Update したときに、二重に INSERT されてしまうなどの問題を引き起こします。

そのため、Update 後には AcceptChanges メソッドを呼び出して、
RowState を最新の値に戻すようにします。

AcceptChanges を呼び出した場合、"Modified" や "Added" な行は、
「新しい値」を使って "Unchanged" 状態へと遷移します。
"Deleted" な行は、DataTable.Rows から取り除かれ、"Detached" となります。

AcceptChanges は、いわば擬似的なコミット操作ですね。

一方、ロールバックに相当する操作は RejectChanges メソッドです。こちらは、
"Added" な行を未登録状態、すなわち DataTable.Rows から取り除いて "Detached" とします。
"Modified" な行は「編集前の値」を使って "Unchanged" 状態へと戻し、
"Deleted" な行は、削除フラグを取り消して "Unchagend" 状態とします。
引用返信 編集キー/
■73960 / inTopicNo.5)  Re[4]: SqlDataAdapterのUpdateコマンドエラー?
□投稿者/ しろくま5 (3回)-(2014/11/17(Mon) 19:09:26)
No73958 (魔界の仮面弁士 さん) に返信
> ■No73956 (しろくま5 さん) に返信
>> dim ds as new DataSet
>> adp.fill(ds)
>> dim dt as DataTable = ds.tables(0)
>> connect.close()
>
> これだけでは不十分だったりします。
>
> No73956 にて、DataRow の RowState プロパティについて触れていますが、
> このプロパティのことはご存知でしょうか?
>
> ---------
> SelectCommand で取得したばかりの未加工のデータは、
> DataRow の RowState プロパティが「Unchanged」の状態です。
>
> そしてその行を編集すると、RowState が「Modified」へと変化します。
> 編集前の値と編集後の値を取り出すことも出来ます。
>
>  Dim row As DataRow = ds.tables(0).Rows(0)
>  oldValue = row("列名", DataRowVersion.Original)
>  newValue = row("列名", DataRowVersion.Current)
>
>
> そして、「削除」した場合は DataTable.Rows から取り除かれるのではなく、
> 「Deleted」状態となります。いわゆる削除フラグが立てられた状態です。
> このモードの時は、
>  oldValue = row("列名", DataRowVersion.Original) '削除する前の値
>  'newValue = row("列名", DataRowVersion.Current) '削除済みの行なのでエラー!
> という動作になります。
>
>
> そして追加した行については、「Added」状態です。
> .Rows.Add で追加した場合などがこの状態ですね。
> ---------
>
> Update メソッドに DataTable を引き渡した場合、
> 各行の RowState プロパティが参照され、各コマンドに引き渡されます。
>
>  "Modified" な行は UpdateCommand 経由で UPDATE の SQL へ
>  "Deleted" な行は DeleteCommand 経由で DELETE の SQL へ
>  "Added" な行は InsertCommand 経由で INSERT INTO の SQL へ
>
> という感じです。Unchanged な行は編集の必要が無いので無視されます。
>
>
> 今回の場合、
>  adp.fill(ds)
>  dim dt as DataTable = ds.tables(0)
> は、全ての行が Unchanged なので無視され、
>  table.Rows.Add(row)
> は、Added がマークされているため、登録されたわけです。
> -----------
>
> なお、Update メソッドを呼び出した後も、RowState を変更せずにおくと、
> 再度 Update したときに、二重に INSERT されてしまうなどの問題を引き起こします。
>
> そのため、Update 後には AcceptChanges メソッドを呼び出して、
> RowState を最新の値に戻すようにします。
>
> AcceptChanges を呼び出した場合、"Modified" や "Added" な行は、
> 「新しい値」を使って "Unchanged" 状態へと遷移します。
> "Deleted" な行は、DataTable.Rows から取り除かれ、"Detached" となります。
>
> AcceptChanges は、いわば擬似的なコミット操作ですね。
>
> 一方、ロールバックに相当する操作は RejectChanges メソッドです。こちらは、
> "Added" な行を未登録状態、すなわち DataTable.Rows から取り除いて "Detached" とします。
> "Modified" な行は「編集前の値」を使って "Unchanged" 状態へと戻し、
> "Deleted" な行は、削除フラグを取り消して "Unchagend" 状態とします。


迅速なご返信ありがとうございます。
なるほど、よくわかりました!
このRowStateで判断してUPDATEやDELETE処理を行っていたのですね…

ご回答頂きありがたく思うのですが、どうやらDataAdapter経由ではDBへの書き込み処理が遅いようで
新規追加に向いてないかなと思い、SQL文かストアドプロシージャで初回のDB登録を行おうと思います。

レコード更新処理はそのままDataAdapterで行おうかと思っておりますので、今回の件を参考にして組んでみたいと思います。

ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -