オプティミスティック コンカレンシー チェックのために ConcurrencyMode が "Fixed" に設定された整数プロパティ (ROW_VERSION という名前) を持つエンティティ クラスがあります。このタイプのエンティティを保存する前に、アプリケーション コードでこの列の値をインクリメントします (そのため、StoreGeneratedPattern は None に設定されます)。これは、変更を保存するときにうまく機能します。
ここで、以前に読み込まれたエンティティ (ROW_VERSION = x) があり、新しい DbContext を作成し、このエンティティをアタッチして、このエンティティを含むクエリを発行したときに、同時実行エラーを検出したいと考えています。問題は、ROW_VERSION が別のクライアント アプリケーションによってインクリメントされた場合 (ROW_VERSION = x + 1)、クエリ中にこれが検出されないことです。これは、添付されたエンティティの値が明らかに優先されるためです (これは、一般的な列の値に対して完全に意味があります)。 )。
一方、並行性チェック列の場合、EF が値を現在のデータベース値で更新すると、期待値と比較できるので便利です。または、クエリの実行からスローされた例外が許容されます。
.NET 4.0 でエンティティ フレームワーク 4.3 を使用しています。
編集 (Gert Arnold からのコメントに応じて):
私は自分の問題をもう少し明確にしようとします...
私のアプリケーションが一般的にどのように機能するかについてのメモ:
使用可能なエンティティ オブジェクトを表示するツリービューがあり、いずれかを選択すると、完全なエンティティが DB から読み込まれ、編集可能な詳細ビューに表示されます。
エンティティ オブジェクトへの変更はすぐには保存されませんが、メモリにキャッシュされるため、ユーザーが保存ボタンを押すと、さまざまなエンティティ オブジェクトの変更が蓄積され、まとめて保存されます。
DbContext は、クエリと変更の保存用に別々に作成されます (つまり、常に同じ DbContext を持っているわけではありませんが、必要に応じてインスタンス化されます)。
詳細ビューに表示するためにエンティティ オブジェクトが読み込まれると、以前に変更された (キャッシュされた) すべてのエンティティ オブジェクトが、最初にクエリに使用される DbContext にアタッチされます。次に、実際のクエリが発行されます。そのため、エンティティ オブジェクトをクエリすると、データベースからのバージョンではなく、結果として変更されたバージョンが取得される前に変更されました (その間に変更された可能性があります)。
だからここに私の問題を示す例があります:
クライアント アプリ 1 は、ROW_VERSION = 1 でエンティティ オブジェクトを読み込み、DbContext を破棄し、さらに編集するためにこのエンティティ オブジェクトへの参照を保持します。
クライアント アプリ 2 は、手順 1 と同じエンティティ オブジェクトを読み込み、プロパティを変更して、変更を保存します。これにより、DB の ROW_VERSION が増加します (現在は 2 です)。
クライアント アプリ 1 のユーザーは、エンティティ オブジェクトのいくつかのプロパティを変更します (これは、ROW_VERSION が 1 でメモリ内にあります)。
クライアント アプリ 1 は、変更を保存する前に、他のエンティティ オブジェクトを表示用に読み込み、最終的に問題のエンティティ オブジェクトを再度選択します (たとえば、行った変更を確認するため)。これにより、結果に既に変更されたエンティティ オブジェクトが含まれるクエリが発生します (実際のクエリがデータベースに送信される前に DbContext にアタッチされるため)。
ここに私の問題があります: この時点で、エンティティ フレームワークは、添付されたオブジェクトの ROW_VERSION を実際のクエリ結果のオブジェクトの ROW_VERSION と比較し、不一致を検出して、たとえば例外をスローすることができます。
ただし、代わりに、EF は ROW_VERSION プロパティを、クライアントによって変更された可能性のある他のすべてのプロパティと同様に扱います。
したがって、EF が ROW_VERSION プロパティを特別に扱い、すべてのクエリでその値を比較して、他のクライアントによる変更を検出することを望みます。このようにして、SaveChanges 呼び出しを待機するよりも早く同時実行状況を検出します。