1 つのグローバル Entity Framework DbContext
の作成 Webアプリケーションでは非常に悪いです。 DbContext
クラスはスレッドセーフではありません (また、Entity Framework v1 の ObjectContext
についても同様です) クラス)。 作業単位
の概念に基づいて構築されています これは、単一のユースケース、つまりビジネストランザクションを操作するために使用することを意味します。 1 つのリクエストを処理するためのものです。
リクエストごとに新しいトランザクションを作成しますが、同じ DbContext
を使用しようとするため、例外が発生します . DbContext
が これが機能しないことがわかったので、これを検出して例外をスローします。
DbContext
データベース内のエンティティのローカル キャッシュが含まれています。一連の変更を行い、最終的にそれらの変更をデータベースに送信できます。単一の静的 DbContext
を使用する場合 、複数のユーザーが SaveChanges
を呼び出す そのオブジェクトで、何がコミットされ、何がコミットされるべきでないかを正確に知るにはどうすればよいでしょうか?
知らないので、すべて保存します 変更されますが、その時点で別のリクエストがまだ変更を行っている可能性があります。運が良ければ、エンティティが無効な状態であるため、EF またはデータベースのいずれかが失敗します。運が悪ければ、無効な状態のエンティティがデータベースに正常に保存され、数週間後にデータが破損していることに気付くかもしれません.
あなたの問題の解決策は、少なくとも 1 つの DbContext
リクエストごと
.理論的にはユーザー セッションでオブジェクト コンテキストをキャッシュできますが、これも悪い考えです。その場合、DbContext
通常、存続期間が長すぎ、古いデータが含まれます (内部キャッシュが自動的に更新されないため)。
DbContext
が 1 つあることにも注意してください。 スレッドごとに、完全な Web アプリケーションに対して 1 つのインスタンスを使用するのと同じくらい悪いです。 ASP.NET はスレッド プールを使用します。つまり、Web アプリケーションの有効期間中に作成されるスレッドの量は限られています。これは基本的に、これらの DbContext
を意味します その場合、インスタンスはアプリケーションの存続期間中存続し、データの古さに関する同じ問題を引き起こします。
DbContext
が 1 つあると思うかもしれません per thread は実際にはスレッド セーフですが、通常はそうではありません。ASP.NET には、開始されたスレッドとは異なるスレッドで要求を終了できる非同期モデルがあるためです (MVC と Web API の最新バージョンでは、任意の数のスレッドが 1 つの要求を順番に処理します)。これは、リクエストを開始して ObjectContext
を作成したスレッドが 最初のリクエストが完了するずっと前に、別のリクエストを処理できるようになる可能性があります。ただし、その要求で使用されるオブジェクト (Web ページ、コントローラー、または任意のビジネス クラスなど) は、引き続きその DbContext
を参照する可能性があります。 .新しい Web リクエストは同じスレッドで実行されるため、同じ DbContext
を取得します。 古いリクエストが使用しているものとしてインスタンス。これにより、アプリケーションで競合状態が再び発生し、1 つのグローバルな DbContext
と同じスレッド セーフの問題が発生します。 インスタンスの原因。