2011-08-11 12 views
1

私のアプリケーションでは、データベーステーブルの内容をユーザーに表示するコントロールがあります。このコントロールは、System.Data.DataSetオブジェクトに表示するデータを保持します。ユーザーはコントロールに表示されているデータを変更することができ、ユーザーが完了するとこのデータはデータベースにコミットされます。SqlDataAdapter.Updateがサイレントに失敗する

ユーザーがコントロールで編集中にデータベーステーブルのデータが一部の外部プロセス(たとえば、一部の行が更新された)によって変更されると問題が発生します。現時点でのデータの正確性の問題を無視して、ユーザーがコントロールで行った変更をコミットし、この外部プロセスによって加えられた変更を上書きすることです。

私はSqlDataAdapterを使用してデータベースを更新しています。上記の使用例では、基になるデータベーステーブルが外部プロセスによって変更されていない場合、SqlDataAdapter.Updateは期待どおりに動作します。ただし、ユーザーが編集中に外部プロセスがテーブルを操作していた場合、SqlDataAdapter.Updateは例外をスローしませんが、更新された行がないことを示す0を返します。データセット内の行に正しいデータがあり、(つまりDataRowState.Modified)の行があることを確認しましたので、私がSqlDataAdapter.Updateメソッドに渡すデータが正しいことがわかります。

私の質問には2つの部分があります。

  1. SqlDataAdapter.Updateは、指定されたデータセットでデータベースを更新しないのはなぜですか?
  2. なぜ静かに失敗していますか?

私はthis blog entryを読んでいると、私のコードはどこにでもAcceptChangesを呼び出さない、と私は私の上に述べてきたように私は行が正しくデータを変更したものとしてマークされていることを知っているDataSetRowStateをチェックしています。

答えて

1

テーブルの構造は何ですか?使用するバージョン管理メカニズム(タイムスタンプ、日時など)は何ですか? SqlDataAdapterが最終的にバージョン管理をどのように処理するかに影響するいくつかの事柄がありますが、テーブルにタイムスタンプがあるか、最終的にすべてをチェックするSqlCommandGetUpdateCommandメソッドを通じて)を生成しています。更新した行の以前の値と比較したデータベース内の行の値(DataRowは比較のために行の前のバージョンを格納します)。

ADO.NETはあなたのためにoptimistic concurrencyを試して維持しようとしているので、そのすべてが重要な役割を果たします。前回のフェッチ後に他の誰かがレコードを変更した場合、更新は行われません。

これは明らかに必要な動作ではありません。ラスト・イン・ウィンズのアプローチが必要です。これを行うには

は、アップデートを実行し、タイムスタンプをチェックしませんSqlCommandに明示的UpdateCommandプロパティを設定SqlDataAdapterに、それが唯一の主キーが指定したDataRowの値に等しいレコードを更新します(またはそれに固有の制約を持つ列の値)を指定します。

+0

タイムスタンプが問題でした。 SqlDataAdapterがSqlCommandBuilderにラップされ、SqlDataAdapterのselectコマンドがタイムスタンプを取得しました。このタイムスタンプは、自動的に生成されたUPDATEコマンドがタイムスタンプをクエリの一部として使用したことを意味します。タイムスタンプを無視した明示的な更新コマンドを作成すると、問題が修正されました。SQLプロファイラを掘り起こすのは楽しいことではないので、私はただちにあなたの答えを見てほしかった:) – CadentOrange

+0

@Philip Goh:私はただちに答えを見たことがあるとは知らない前。 =) – casperOne

関連する問題