28

Entity Frameworkによって生成されるコンテキストオブジェクトは、スレッドセーフではありません。エンティティフレームワークのスレッドセーフティ

2つの別々のエンティティコンテキストを使用すると、スレッドごとに1つずつ(そしてそれぞれSaveChanges()を呼び出します)、これはスレッドセーフなのでしょうか?

// this method is called from several threads concurrently 
public void IncrementProperty() 
{ 
    var context = new MyEntities(); 

    context.SomeObject.SomeIntProperty++; 
    context.SaveChanges(); 
} 

私は、エンティティフレームワークのコンテキストはコンテキストの現在の値が新鮮であるかどうかを追跡する「カウンタ」変数のいくつかの並べ替えを実装して信じています。

  1. 上記のコードでは、別のスレッドから呼び出されます。インクリメント/セーブチェンジをロックする必要がありますか?
  2. もしそうなら、この単純なシナリオでこれを達成するための好ましい方法は何ですか?
+0

* "コンテキストを受信することにより、あなたのリポジトリを変更する必要があるメソッドを呼び出して、非常に簡単な方法でそれを行うにはNinjectの拡張機能があり

http://elvanydev.com/EF-DbContextFactory/

Entity Frameworkはスレッドセーフではありません。 "* - なぜそれを言うのですか? – RPM1984

+0

私はMSDNを参照しています:http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx「ObjectContextクラスはスレッドセーフではありません。 – Harper

+0

ええ、それは私があなたが意味すると思ったものです - 文脈であって実体ではありません。だからあなたはOCのためにシングルトンを使うべきではありません。 – RPM1984

答えて

31

さらに、単一のEntity Frameworkコンテキストで動作するスレッドはスレッドセーフではありません。

スレッドごとに個別のコンテキストのインスタンスがスレッドセーフです。実行の各スレッドがEFコンテキストの独自のインスタンスを持っている限り、あなたはうまくいくでしょう。

この例では、そのコードを任意の数のスレッドから同時に呼び出すことができ、それぞれ独自のコンテキストでうまく動作します。

​​
+0

ありがとうございます。それで、SubmitChanges()を実行したり、いつ何時にSomeIntPropertyの実際の値が読み込まれますか?私は、最初のスレッドが値を3に増やしても、2番目のスレッドは潜在的に2の値をまだキャッシュしているのでしょうか、それともその値を取得しますか? – Harper

+0

私はあなたの例のいくつかの重要な側面を見落としました。まず、「SomeObject」を取得しインスタンス化するコードはありません。したがって、示されているように、コードは機能しません。コンテキスト間にキャッシュ、バッファまたはロックの共有はありません。したがって、コンテキストインスタンスを持つ各スレッドは、プロセスが2つの異なるマシン上で実行されていると考えるように考えることができます。したがって、それに応じてデータベースの並行性の問題に対処する必要があります。 –

+1

データベースと並行して処理するためには、オプティミスティック並行処理またはデータベース処理を実装する必要があります。 –

0

「SomeObject.SomeIntProperty」は静的です。これは、エンティティがスレッドセーフであることとは関係ありません。マルチスレッド環境で静的変数に書き込む場合は、スレッドの安全性を確保するために必ずダブルチェックロックでラップする必要があります。

0

あなたはこのを見て、代わりにインスタンスそれ自体の工場としてごDbContextを注入工場のアプローチを使用することができます。

しかし、私は次のように、このためのブロック「を使用して」を実装することをお勧め:https://github.com/vany0114/EF.DbContextFactory

インスタンスの作成をリポジトリにハードコードするのはより安全です。ただkernel.AddDbContextFactory<YourContext>();はまた、あなたがによって生成されたオブジェクトFunc<YourContext>