Entity-framework-concurrency

提供:Dev Guides
移動先:案内検索

Entity Framework-並行性

データアクセスの開発者は、「複数の人が同じデータを同時に編集しているとどうなりますか?」というデータの同時実行性に関する質問に答えるのに苦労しています。

  • 幸運なことに、「問題なく、最後に勝った」というビジネスルールに対処できます。
  • この場合、並行性は問題になりません。 おそらく、それはそれほど単純ではなく、すべてのシナリオを一度に解決するための特効薬はありません。
  • 既定では、Entity Frameworkは「勝者の最後の1つ」のパスを使用します。つまり、データが取得されてからデータが保存されるまでに誰かがデータを更新した場合でも、最新の更新が適用されます。

よりよく理解するために例を挙げましょう。 次の例は、Courseテーブルに新しい列VersionNoを追加します。

コース表

デザイナーに移動し、デザイナーウィンドウを右クリックして、データベースから更新モデルを選択します…

デザイナー

別の列がコースエンティティに追加されていることがわかります。

コースエンティティ

次の図に示すように、新しく作成された列VersionNoを右クリックして[プロパティ]を選択し、ConcurrencyModeをFixedに変更します。

新規作成列

Course.VersionNoのConcurrencyModeをFixedに設定すると、コースが更新されるたびに、UpdateコマンドはEntityKeyとVersionNoプロパティを使用してコースを検索します。

簡単なシナリオを見てみましょう。 2人のユーザーが同じコースを同時に取得し、ユーザー1がそのコースのタイトルをMathsに変更し、ユーザー2の前に変更を保存します。 その後、ユーザー2がユーザー1が変更を保存する前に取得したコースのタイトルを変更すると、ユーザー2は同時実行例外 "User2:Optimistic Concurrency exception occurred" を取得します。

using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;

namespace DatabaseFirstDemo {

   class Program {

      static void Main(string[] args) {

         Course c1 = null;
         Course c2 = null;

        //User 1 gets Course

         using (var context = new UniContextEntities()) {
            context.Configuration.ProxyCreationEnabled = false;
            c1 = context.Courses.Where(s ⇒ s.CourseID == 1).Single();
         }

        //User 2 also get the same Course

         using (var context = new UniContextEntities()) {
            context.Configuration.ProxyCreationEnabled = false;
            c2 = context.Courses.Where(s ⇒ s.CourseID == 1).Single();
         }

        //User 1 updates Course Title
         c1.Title = "Edited from user1";

        //User 2 updates Course Title
         c2.Title = "Edited from user2";

        //User 1 saves changes first

         using (var context = new UniContextEntities()) {

            try {
               context.Entry(c1).State = EntityState.Modified;
               context.SaveChanges();
            } catch (DbUpdateConcurrencyException ex) {
               Console.WriteLine("User1: Optimistic Concurrency exception occurred");
            }
         }

        //User 2 saves changes after User 1.
        //User 2 will get concurrency exection
        //because CreateOrModifiedDate is different in the database

         using (var context = new UniContextEntities()) {

            try {
               context.Entry(c2).State = EntityState.Modified;
               context.SaveChanges();
            } catch (DbUpdateConcurrencyException ex) {
               Console.WriteLine("User2: Optimistic Concurrency exception occurred");
            }
         }
      }
   }
}