16

Entity Framework 4.0 を使用してアクセスする MySQL サーバーがあります。データベースにはWorksという名前のテーブルがあり、そこに数が含まれています。Asp.net で Web サイトを開発しています。このテーブルは、同時にもう 1 人のユーザーにアクセスできます。そして、この状況は間違った激しさの問題を引き起こします。

そのような私のコード:

dbEntities myEntity = new dbEntities();

var currentWork = myEntity.works.Where(xXx => xXx.RID == 208).FirstOrDefault();
Console.WriteLine("Access work");

if (currentWork != null)
{
    Console.WriteLine("Access is not null");
    currentWork.WordCount += 5;//Default WordCount is 0
    Console.WriteLine("Count changed");
    myEntity.SaveChanges();
    Console.WriteLine("Save changes");
}
Console.WriteLine("Current Count:" + currentWork.WordCount);

複数のスレッドが同時にデータベースにアクセスすると、最後の変更のみが残ります。

現在の出力:

t1: スレッド 1 - t2: スレッド 2

t1: アクセス作業

t2: アクセス作業

t2: アクセスが null ではない

t1: アクセスが null ではない

t1: カウント変更

t2: カウント変更

t1: 変更を保存

t2: 変更を保存

t1: 現在のカウント: 5

t2: 現在のカウント: 5

期待される出力:

t1: アクセス作業

t2: アクセス作業

t2: アクセスが null ではない

t1: アクセスが null ではない

t1: カウント変更

t2: カウント変更

t1: 変更を保存

t2: 変更を保存

t1: 現在のカウント: 5

t2: 現在のカウント: 10

このコードはアトミックではないため、この問題が発生する理由はわかっています。アトミック操作を有効にするにはどうすればよいですか?

4

2 に答える 2

0

次の方法は、単一のプロセスでサイトをホストしている場合に機能します (Web ファームや Web ガーデンでは機能しません)。

   private static readonly Locker = new object();

   void Foo()
   {
          lock(Locker)
          {
                 dbEntities myEntity = new dbEntities();

                 var currentWork = myEntity.works.Where(xXx => xXx.RID == 208).FirstOrDefault();
                 Console.WriteLine("Access work");

                 if (currentWork != null)
                 {
                     Console.WriteLine("Access is not null");
                     currentWork.WordCount += 5;//Default WordCount is 0
                     Console.WriteLine("Count changed");
                     myEntity.SaveChanges();
                     Console.WriteLine("Save changes");
                 }
                 Console.WriteLine("Current Count:" + currentWork.WordCount);
          }
   }

他にできることは、ObjectContext を介して生の SQL クエリを使用することです。

   if (currentWork != null)
             {
                 Console.WriteLine("Access is not null");
                 myEntity.ExecuteStoredCommand("UPDATE works SET WordCount = WordCount + 5 WHERE RID = @rid", new MySqlParameter("@rid", MySqlDbType.Int32){Value = 208)
                 Console.WriteLine("Count changed");

             }
    var record = myEntity.works.FirstOrDefault(xXx => xXx.RID == 208);
    if(record != null)
        Console.WriteLine("Current Count:" + record .WordCount);
于 2013-07-31T13:13:40.737 に答える