- PR -

OleDbDataAdapterを使用したDB更新

投稿者投稿内容
kazu
会議室デビュー日: 2005/07/28
投稿数: 9
投稿日時: 2005-07-30 02:07
Jitta様お答えありがとうございます。

>これは“データベースからは”削除しません。「この行は削除します」とマークするだけです。
言葉が足らなくて申し訳ありません。DataRow.Deleteを行った後にUpDateメソッドを実行すると、SelectでとってきたDataTableの中が削除されDBが更新されます。これですとOleDbCommandのDeleteのSQLが意味を成さないような気がするという意味です。

UpDateメソッド後に1レコードごとにRowStateがUpdateかDelete等かを見ていき、OleDbCommandのUpdate等それぞれのSQLを実行し該当条件の処理を行うという流れでよいのでしょうか。RowStateがUpdate等が複数の場合は、そのたびにSQLが実行されるのでしょうか。SQLの該当レコードが複数行だとそのたびに複数レコード更新されるのでしょうか。

>Fill メソッドで SelectCommand を使ってデータベースから取得し、挿入、削除、変更を行い、
挿入ですとNewRow、削除ですとDeleteだと思うのですが、変更の場合は何を使えばよろしいのでしょうか。

>それぞれの行の RowState によって DeleteCommand, InsertCommand, UpdateCommand が使われてデータベースに反映される。
削除の場合はDataRow.DeleteでRowStateをdeleteにし、UpDateで更新、という形で問題ないのでしょうか。


ご教授ください。宜しくお願い致します。
長くなり読みにくくて申し訳ありません。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-07-30 05:58
引用:

kazuさんの書き込み (2005-07-30 02:07) より:

>これは“データベースからは”削除しません。「この行は削除します」とマークするだけです。
言葉が足らなくて申し訳ありません。DataRow.Deleteを行った後にUpDateメソッドを実行すると、SelectでとってきたDataTableの中が削除されDBが更新されます。これですとOleDbCommandのDeleteのSQLが意味を成さないような気がするという意味です。


 え?え〜っと、そういう問いが返ってくるとは、予想していませんでした。。。
 ん〜〜〜???『意味をなさない』とは、どういうことでしょう?『DataRow.Deleteを行った後にUpDateメソッドを実行すると、SelectでとってきたDataTableの中が削除されDBが更新されます』という動きをする仕様です。

 DataAdapter.Update メソッドが実行されると、このメソッドの引数として渡された DataRow のコレクションを、最初から最後までチェックします。
コード:
foreach DataRow row in argument.DataRowCollection
    swtch (row.RowState) {
        case DataRow.Deleted:
            this.DeleteCommand.ExecuteNoQuery();
            break;
        case DataRow.Added:
            this.InsertCommand.ExecuteNoQuery();
            break;
        case DataRow.Modified:
            this.UpdateCommand.ExecuteNoQuery();
            break;
        }
    }
}


このような感じのコードが実行される、と考えてください。ですから、DataAdapter.Update メソッドを実行して初めて、DeleteCommand その他が使われます。

 adapter は2つのものを接続するものです。ここで2つのものというのは、データベースシステムと、メモリ上のデータベースです。Fill メソッドで DBMS からメモリへ、Update メソッドでメモリから DBMS へ、データを移します。この移す作業を実行するために、SelectCommand などが使われます。

 という説明でわかっていただけるでしょうか?


引用:

UpDateメソッド後に1レコードごとにRowStateがUpdateかDelete等かを見ていき、OleDbCommandのUpdate等それぞれのSQLを実行し該当条件の処理を行うという流れでよいのでしょうか。


 これが Update メソッド内部で行われていることを指すのであれば、そうです。


引用:

RowStateがUpdate等が複数の場合は、そのたびにSQLが実行されるのでしょうか。SQLの該当レコードが複数行だとそのたびに複数レコード更新されるのでしょうか。


 そうです。そのため、WHERE 句で、必ず1行になるようにする必要があります。
 とはいえ、影響を受ける行が無い場合は例外があがりますが、複数行が影響を受けても、通知はありません・・・たぶん。


引用:

挿入ですとNewRow、削除ですとDeleteだと思うのですが、変更の場合は何を使えばよろしいのでしょうか。


 DataRow.Item() で、直接変更します。


引用:

>それぞれの行の RowState によって DeleteCommand, InsertCommand, UpdateCommand が使われてデータベースに反映される。
削除の場合はDataRow.DeleteでRowStateをdeleteにし、UpDateで更新、という形で問題ないのでしょうか。


 そうですが、DataRow.RowState は読み取り専用です。Delete メソッドを使ったり、Item プロパティなどから値を変更すると、内部で変更されます。
 Added には、DataTable に追加したときに変わります。
_________________
kazu
会議室デビュー日: 2005/07/28
投稿数: 9
投稿日時: 2005-08-01 10:54
Jitta様、お答えありがとうございました。

>WHERE 句で、必ず1行になるようにする必要があります。
このことがわからなかったため、SQLの内容から該当レコードが複数行同時にすべて更新されるものと思い込んでおりました。(UpDateメソッドでSQLが実行され該当レコードがすべて更新されると思っておりました。)1行になるようにしなければならなかったのですね。

>DataRow.Item() で、直接変更します。
DataRow.Item(i)="" と更新するとき変更内容を正確に記述しなくても(別の値に変更したい場合、空文字""等にしても)DataRow.RowStateがModifiedになっているので、UpDateメソッドでUpdateCommandのSQLが実行され正しく更新されるということでよいのでしょうか。

ご教授ください。宜しくお願い致します。
kazu
会議室デビュー日: 2005/07/28
投稿数: 9
投稿日時: 2005-08-01 11:15
引用:

kazuさんの書き込み (2005-08-01 10:54) より:

>DataRow.Item() で、直接変更します。
DataRow.Item(i)="" と更新するとき変更内容を正確に記述しなくても(別の値に変更したい場合、空文字""等にしても)DataRow.RowStateがModifiedになっているので、UpDateメソッドでUpdateCommandのSQLが実行され正しく更新されるということでよいのでしょうか。




すみません。今確認してみたところ正しく入力しないと正しく変更されませんでした。
SQLのパラメータの値と、Itemプロパティを変更した値を同じにしなければならないのでしょうか。
UpDateメソッド実行時にDataRow.RowStateがModifiedだとUpdateCommandのSQLが実行されますが、異なった場合、SQLより、Itemプロパティで変更した値の方が採用されるのでしょうか。

ご教授ください。宜しくお願い致します。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-08-02 05:03
 まず、前回の補足。

> とはいえ、影響を受ける行が無い場合は例外があがりますが、
> 複数行が影響を受けても、通知はありません・・・たぶん。
 UpdateCommand, InsertCommand, DeleteCommand とも、SQL 文を実行して何行に影響を与えようが、通知はありません。戻り値で、影響を受けた行数が判ります。
 しかし、DataAdapter.Update メソッドを使用したときに限り、影響を受けた行が0件だと、同時実行違反として例外が上がります。


引用:

>DataRow.Item() で、直接変更します。
DataRow.Item(i)="" と更新するとき変更内容を正確に記述しなくても(別の値に変更したい場合、空文字""等にしても)DataRow.RowStateがModifiedになっているので、UpDateメソッドでUpdateCommandのSQLが実行され正しく更新されるということでよいのでしょうか。

すみません。今確認してみたところ正しく入力しないと正しく変更されませんでした。
SQLのパラメータの値と、Itemプロパティを変更した値を同じにしなければならないのでしょうか。
UpDateメソッド実行時にDataRow.RowStateがModifiedだとUpdateCommandのSQLが実行されますが、異なった場合、SQLより、Itemプロパティで変更した値の方が採用されるのでしょうか。


 えっと…書いてあることがよく解りません。
 DataAdapter.Update を実行するのですから、パラメータで指定した値は無視され、列名で指定した列の、その行の値が使われているはずです。そうでなければ、すべての行に同じ値しか設定できなくなってしまいますから。

 ですから、『DataRow.RowStateがModifiedになっているので、UpDateメソッドでUpdateCommandのSQLが実行され(る)』この部分だけ取り出せば「正しい」ですが、だからといって『DataRow.Item(i)="" と更新するとき変更内容を正確に記述しなくても(よい)』わけではありません。

_________________
にしざき
ぬし
会議室デビュー日: 2003/06/30
投稿数: 304
投稿日時: 2005-08-02 05:23
補足。
>  DataAdapter.Update を実行するのですから、パラメータで指定した値は無視され、
> 列名で指定した列の、その行の値が使われているはずです。
> そうでなければ、すべての行に同じ値しか設定できなくなってしまいますから。
この部分はちと不正確で、パラメータに (DataAdapter.Update() を実行する前に) 指定した値は有効です。ただし、パラメータの SourceColumn を指定している場合は更新対象の DataRow の当該列 (の SourceVersion で指定したバージョン) の値が設定されます。

とはいっても、大概の場合はそれぞれのレコード毎に異なる値を設定させたいでしょうし、その場合には DataRow から値を取得するのが簡単だということになります。

kazu
会議室デビュー日: 2005/07/28
投稿数: 9
投稿日時: 2005-08-02 11:08
Jitta様、にしざき様お答えありがとうございます。

引用:


 DataAdapter.Update を実行するのですから、パラメータで指定した値は無視され、列名で指定した列の、その行の値が使われているはずです。そうでなければ、すべての行に同じ値しか設定できなくなってしまいますから。




例えば、「 UPDATE TableName SET col3 = ?, col4 = ?, 更新日時 = SYSDATE WHERE col1 = ? AND col2 = ? 」 というSQLを設定し、

cmdUpd.Parameters.Add("@col3", OleDbType.VarChar, 1, "col3")
cmdUpd.Parameters.Add("@col4", OleDbType.VarChar, 1, "col4")
cmdUpd.Parameters.Add("@col1", OleDbType.VarChar, 3, "col1 ").SourceVersion = DataRowVersion.Original
cmdUpd.Parameters.Add("@col2", OleDbType.VarChar, 5, "col2").SourceVersion = DataRowVersion.Original

cmdUpd.Parameters("@col3").Value = 1
cmdUpd.Parameters("@col4").Value = 1
cmdUpd.Parameters("@col1").Value = ABC
cmdUpd.Parameters("@col2").Value = DEF

このようにパラメータを設定します。
col1、col2が主キーなのでUPDATESQLの該当レコードは1レコードのみです。
SELECTでとってきたDataTableも1レコードのみです。(SELECTとUPDATEの対象レコードは同じで、SELECTの内容をUPDATEしようというものです。)

パラメータ設定後に

dt.Rows(0).item(2) = 5
dt.Rows(0).item(3) = 6

のように値を設定し、DataAdapter.Updateを行った場合、SQLが実行されるが、パラメータの値のSQL「1」「1」ではなく、後に設定した値、「5」「6」に更新されるということでよろしいのでしょうか。

でしたら、後で値を設定せずに、SQLでパラメータの値「1」「1」に更新する場合はどのようにすれば良いのでしょうか。

ご教授ください。宜しくお願い致します。
にしざき
ぬし
会議室デビュー日: 2003/06/30
投稿数: 304
投稿日時: 2005-08-02 12:47
前述したように、パラメータの値のうち DataRow から取得したくないものについては
SourceColumn を指定しなければよいことになります。
当該パラメータに関する Add() メソッドを、3引数のものに変えれば(第4引数を削除)よいと思います。

# なぜ DataAdapter / DataSet を使うのかがわかりませんが…

スキルアップ/キャリアアップ(JOB@IT)