.NET + EF アプリケーションを作成しました。すべてが単一のスレッドで正常に動作します。複数のスレッドでは、別の話です。
私の EF オブジェクトには、整数カウンターがあります。このプロパティは、"Concurrency Mode = Fixed" としてマークされています。基本的に、私がやろうとしているのは、複数のスレッドでこのカウンターを更新することです。この操作のように:
this.MyCounter -= 1;
同時実行モードが「固定」に変更されたため、既に変更されているプロパティを更新しようとすると、OptimisticConcurrencyException
がスローされます。
この同時実行の問題を解決するために、次のコードを使用しています。
while (true)
{
try
{
this.UsageAmount -= 1; // Change the local EF object value and call SaveChanges().
break;
}
catch (OptimisticConcurrencyException)
{
Logger.Output(LoggerLevel.Trace, this, "concurrency conflict detected.");
EntityContainer.Instance.Entities.Refresh(RefreshMode.StoreWins, this.InnerObject);
}
}
このコードの結果は、無限 (またはおそらくそのように見える) ループになります。this.UsageAmount -= 1
throw を呼び出すたびにOptimisticConcurrencyException
、ループが再度実行されます。
MyEntityContainer.Instance.Entities
は、EF コンテキスト PER THREAD を提供するシングルトン クラスです。これは、すべてのスレッドが固有のコンテキストを持つことを意味します。コード:
public sealed class EntityContainer
{
#region Singlethon Implemantation
private static Dictionary<Thread, EntityContainer> _instance = new Dictionary<Thread,EntityContainer> ();
private static object syncRoot = new Object();
public static EntityContainer Instance
{
get
{
if (!_instance.ContainsKey(Thread.CurrentThread))
{
lock (syncRoot)
{
if (!_instance.ContainsKey(Thread.CurrentThread))
_instance.Add(Thread.CurrentThread, new EntityContainer());
}
}
return _instance[Thread.CurrentThread];
}
}
private EntityContainer()
{
Entities = new anticopyEntities2();
}
#endregion
anticopyEntities2 _entities;
public anticopyEntities2 Entities
{
get
{
//return new anticopyEntities2();
return _entities;
}
private set
{
_entities = value;
}
}
}
ところで、Entities.Refresh
メソッドを呼び出した後、動作しているように見えます (オブジェクトの状態は Unchanged であり、プロパティ値はデータベースに存在するものとまったく同じです)。
この並行性の問題を解決するにはどうすればよいですか?