2

EF4を使用するいくつかのリポジトリ パターンプロジェクトに、次の疑似コードがあります。

public void Delete(int someId)
{
   // 1. Load the entity for that Id. If there is none, then null.
   // 2. If entity != null, then DeleteObject(..);
}

非常に単純ですが、実行時エラーが発生します:-

ConcurrencyException: Store、Update、Insert、または Delete ステートメントが予期しない数の行 (0) に影響を与えました。

今、これが起こっていることです:-

  1. EF4 の 2 つのインスタンスがアプリで同時に実行されています。
  2. インスタンス A が delete を呼び出します。
  3. インスタンス B は、1 ナノ秒後に削除を呼び出します。
  4. インスタンス A がエンティティをロードします。
  5. インスタンス B もエンティティをロードします。
  6. インスタンス A はそのエンティティを削除します - クールなバナナ。
  7. インスタンス B はエンティティを削除しようとしますが、エンティティは既に削除されています。そのため、ノーカウントまたはそうでないものは0であり、1..またはそのようなものを期待していました。基本的に、削除するはずのアイテムが削除されていないことがわかりました (ほんの数秒前に発生したため)。

これが競合状態か何かのようなものかどうかはわかりません。

とにかく、2番目の呼び出しがクラッシュしないように、ここでできるトリックはありますか? 私はそれをストアドプロシージャにすることができました..しかし、今はそれを避けたいと思っています。

何か案は?選択が呼び出されたときにその行(およびその行のみ)をロックできるかどうか疑問に思っています...行ロックが解除されるまでインスタンスBを強制的に待機させます。その時までに、行は削除されるため、インスタンス B が選択を行うと、データは存在しません..削除されることはありません。

4

1 に答える 1

0

通常、OptimisticConcurrencyExceptionをキャッチしてから、ビジネスモデルに適した方法で問題を処理します。次に、SaveChangesを再度呼び出します。

try
{
    myContext.SaveChanges();
}
catch (OptimisticConcurrencyException e)
{
    if (e.StateEntries.FirstOrDefault() is DeletingObject)
        myContext.Detach(e.StateEntries.First();
    myContext.SaveChanges();
}

それを回転させて、どのように動作するかを確認します-テスト/コンパイルされていないなど-削除しようとしているエンティティのタイプとして、DeleteingObjectを使用しました。エンティティタイプの代わりに使用してください。

于 2010-05-14T12:25:47.693 に答える