問題は、Visual Studio で WebAPI プロジェクトを停止すると...
ASP.NET 内で WebAPI をホストしている場合 (Visual Studio の標準 WebAPI プロジェクトは、このようなプロジェクト タイプを作成します)、デバッガーを停止しても、アプリケーションを実行しているプロセスは実際には停止しませんが、そのアプリケーションからデバッガーを切り離すだけです。実行中のプロセスは、たとえば IIS Express を開発テスト サーバーとして使用している場合、Web サーバーのワーカー プロセスであり、存続します。(通常、Windows 画面の右下隅にあるシステム トレイに小さなアイコンがあります。そこでプロセスを停止すると、プロセスは「実際に」強制終了されます。)
... SQL 管理スタジオで DB を開き、物理行を削除します (上記で投稿した 10 項目を表します) ...
DbSet<T>.Local
メモリ内のコレクションです。EF コンテキスト外の別のプロセス (SSMS) でデータベースから行を削除したことは「わかりません」。
...その後、ビジュアル スタジオで webAPI のデバッグを再開します。
上記のワーカー プロセスがまだ実行されている場合、デバッガーを再起動しても新しいプロセスは開始されませんが、デバッガーは既存のプロセスにアタッチされます。このプロセスのすべてがまだそこにあります。
(フィドラーを介して) GET 要求を実行し、コントローラーの get メソッドのブレークポイントを介して dbset を検査すると、基になるアイテムが存在しないにもかかわらず、10 個のアイテムがまだ dbset.Local プロパティにあることがわかります。 DB。
検査、反復DbSet<T>.Local
、または呼び出しDbSet<T>.Local.ToList()
はデータベース クエリを実行しないため、DB テーブルが空であることは認識されません。メモリ内の古いデータを返すだけです。
GET が効果的に dbset.ToList() を呼び出して完了すると、空の結果セットが得られます。
DbSet<T>.ToList()
実際にはデータベースクエリを実行するため、テーブルが空であることがわかり、その結果が返されます。
その後、同じ 10 個のアイテムを再投稿すると、10 個のアイテムが再び DB に正常に到達しますが、dbset.Local のローカル コレクションには 20 個のアイテムが含まれています!?
DbSet<T>.Local
古い結果がまだメモリに残っていたからです。データベースへの以前のクエリは、正しいクエリ結果を提供するために空のリストを返しましたが、コレクションDbSet<T>.ToList()
がクリアされたことを意味するわけではありません。Local
データベース内に (新しいキー値を持つ) 新しいエンティティが見つかった場合、このエンティティはLocal
コレクションに追加されます (11 項目を表示)。ただし、クエリによって からアイテムが削除されることはありませんLocal
。
WebAPI プロジェクトを再起動した後、dbset.Local が空でないのはなぜですか? デバッグを停止してコーヒーを飲み、デバッグを再開すると、dbset.Local コレクションにはまだ 20 個のアイテムが含まれています。
コーヒーを 10 杯試してみてください :) 非アクティブ状態が長時間続くと、ワーカー プロセスが自動的にシャットダウンする場合があります。どれくらいの時間がかかるのか、IIS Express で発生するのかどうかはわかりません。
これは私が遭遇しているキャッシングの問題ですか? Visual Studio でプロジェクトが再起動されるたびにこれを処理して dbset.Local をクリアするために、プロジェクトの起動コードで何かする必要がありますか?
はい、Local
コレクションにキャッシュされたこれらのエンティティは、複数の Web 要求で同じコンテキスト インスタンスを再利用していることを示しているため、(潜在的に) 非常に大きな問題です。これは、依存している場合Local
や、他の多くの問題や例外 (たとえば、既に にあるエンティティのような同じキーを持つエンティティをアタッチする場合Local
など) に間違った結果をもたらす可能性があります。一般に、Web リクエストの開始時に新しいコンテキスト インスタンスを作成し、この単一のリクエストの処理中にそれを使用し、リクエストの終了時に破棄することがベスト プラクティスであり、推奨されます。コンテキストを破棄すると、ガベージ コレクションのためにオブジェクトが解放されます。のLocal
新しいコンテキスト インスタンスのコレクションは、次のリクエストで空になります。(これとその方法(コントローラーごと、手動、依存性注入など)は、それ自体が特別な主題です。「リクエストごとのエンティティフレームワークコンテキスト」または同様のキーワードをグーグルで検索して始めてください。)
また、dbset.Local が DB に設定された一意の名前の制約を尊重せず、dbset.Local コレクションへの重複エントリを許可しないのはなぜですか?エラーをスローしないでください。
Entity Framework は一意の制約をサポートしていません (主キーの一意性を除く)。つまり、データベース内の一意のインデックスについて何も知らないだけです。