2016-05-03 2 views
1

私は、同時に実行されるトランザクションを持っています。特定の参照のエントリが存在する場合、データを更新しなければなりません。それに応じて参照を設定してください。これまでのところ、私が持っているコードはこのように書き:ReadCommittedに分離レベルを設定しているにもかかわらず、汚れた読み込みを取得する

using (var context = new MyDbContext()) 
{ 
    using (var scope = context.Database.BeginTransaction(System.Data.IsolationLevel.ReadCommitted)) 
    { 
     try 
     { 
      MyModel model = null; 
      int hasEntry = context.MyModel.Where(x => x.refID == refID).Count(); 
      if (hasEntry == 0) 
      { 
        model = new MyModel(); 
        model.refID = refID; 
      } 
      else 
      { 
        model = context.MyModel.Where(x => x.refID == refID).Single(); 
      } 
      // process model object... 
      if (hasEntry == 0) 
      { 
        context.MyModel.Add(model); 
      } 
      else 
      { 
        context.Entry(model).State = EntityState.Modified; 
      } 
      context.SaveChanges(); 
      scope.Commit(); 
     } 
     catch(Exception) 
     { 
      scope.Rollback(); 
     } 
    } 
} 

場合は2つ(またはそれ以上)の場合は、最初の1つのインサートを実行しますが、その後remaningものは更新されません。侵害されたPKについて不平を言うDBUpdateExceptionをスローします。

更新する必要があるものが実際に挿入しようとしている理由がわかりません。彼らは例外をスローするように既にテーブルに追加されたIDを取得します。

AFAIK IsolationLevel.ReadCommittedは行をロックし、トランザクションが完了したときにそれらを解放する必要があります。ドキュメント(https://msdn.microsoft.com/en-us/library/cc546518.aspx)によると、 "接続が読み取り専用コミットレベルを使用していて、SQL ServerがDMLステートメントの実行中にダーティ行を検出すると、行を現在所有しているトランザクションがコミットまたはロールバックされてから続行されるまで待機します実行。"

インスタンスが最初に挿入されたインスタンスを待っていないため、インスタンスが既に(すでに使用されているIDを使用して)挿入しようとしているため、PK違反が発生するため、

私には何が欠けていますか?

PD:これはC#とentityframeworkを使用した私の最初のプロジェクトです。私はたくさんの検索をしてきましたが、答えが見つからなかったので、質問が愚かなものであれば私を許してください。

答えて

1

これはダーティーリードではなく、使用時間の問題(TOCTOU)のチェック時間です チェックしたときに行が存在しませんでしたが、挿入する前に挿入されました。

これを防ぐ1つの方法は、何らかの種類のロックを使用することです。あなたはまた、挿入を試みることができ、それが失敗した場合、更新を行います。ここで が、その詳細がある(「MyTableというWITH(TABLOCKX、HOLDLOCK)のトップ1 IDを選択」) context.Database.ExecuteSqlCommand:

+0

あなたは正しいですが、私はこのようなロックを適用することによって、問題を解決しました:http://stackoverflow.com/questions/13404061/how-can-i-lock-a-table-on-read-using-entity-framework –

0

「挿入する汚れた行」はありません。両方のプロセスが同時にid=111が存在するかどうか尋ねると、明らかに両方とも「いいえ」になります。通常、PKのアプリ管理値を使用した挿入は、常にtry catchブロックにある必要があります。

関連する問題