LINQ to SQLは、異なるデータコンテキストからのオブジェクトの更新を切断しました
-
07-07-2019 - |
質問
http://geekswithblogs.net/michelotti/archive/2007 /12/17/117791.aspx
C#でASP.NETを使用しており、linq to sqlを使用して、上記リンクのブログにあるデータコンテキストを更新しようとしています。前述のように、テーブルにタイムスタンプフィールドを作成し、次の方法を使用しています。
private void updateRecord(TableName updatedRecord)
{
context db = new context();
db.TableName.Attach(updatedRecord,true);
db.SubmitChanges();
}
私の質問は、データコンテキストでAttachメソッドを呼び出そうとする前に、timestampフィールドをupdatedRecordの何かに割り当てるべきですか?
このコードを実行すると、次の例外が発生します。 System.Data.Linq.ChangeConflictException:行が見つからないか、変更されていません。
オブジェクトをこの更新メソッドに渡す前に、更新するレコードの主キーを含むすべてのフィールドを更新します。デバッグ中、オブジェクトのTimeStamp属性はnullとして表示されます。そのようになっているかどうかはわかりません。
私がこれまでに書いたすべての本とリソースは、これがそれを行う方法であると言っていますが、このTimeStamp属性について詳しく説明しているものはありません。
これは迅速かつ簡単であることを知っているので、誰かが知っているなら、私に知らせてください。
解決
タイムスタンプ列がある場合、レコードを更新するには(バニラオブジェクトから):はい、割り当てる必要があります。そうしないと、オプティミスティックな同時実行性チェックにタイムスタンプを使用できなくなります。
(切断された)オブジェクトを取得するときにタイムスタンプのコピーを取得し、更新するときにこの列を使用して、他のユーザーが行を編集していないことを確認できます。
2つの一般的なシナリオがあります:
1:短命の操作のみを実行している場合は、最初にデータベースからレコードを取得します。オブジェクトに変更を加え、SumbitChanges()[すべて同じデータコンテキストで]を実行します。データコンテキストは同時実行を処理します。
2:オブジェクトを切断する場合(たとえば、しばらくクライアントアプリケーションに渡す場合)、シリアル化などを使用します(LINQ-to-SQLオブジェクトはDataContractSerializerをサポートします(オプションで有効にする必要があります))。サーバーでオブジェクトをシリアル化し、クライアントに渡します-クライアントはコピーに変更を加えて返します。サーバーはそれをデシリアライズし、Attach()およびSubmitChanges()を使用します。メモリ内のレコードには、データベースから抽出されたときのタイムスタンプが残っている必要があるため、レコードが切断されている間はいつでも楽観的な同時実行を実行できます。
他のヒント
テーブルにタイムスタンプフィールドを作成したと言っているので、この列が後で追加された場合、列のプロパティが正しく設定されていない可能性があります。 DBMLデザイナでTimeStamp列のプロパティを確認できます。確認してください:
AutoGenerated = true
Auto-Sync = Always
Time Stamp = True
Update Check = Never
サーバーのデータ型は rowversion NOT NULL
自動生成および常に同期するように設定されていない場合、挿入が行われたときに変更していないため、行バージョンは挿入から返されません。この値はデータベースによって生成されますが、DataContextは適切に処理できるようにこれを知る必要があります。
さらに、タイムスタンプ列があるので、他のすべての列の UpdateCheck
を Never
に設定する必要があります。