2

私はエンティティフレームワークから非常に奇妙な動作をしていました。ブラウザから取得したオブジェクトが切断/分離されるように、WebApi アプリケーションをコーディングしています。返されるデータは、データベース内の特定のテーブルと一致しないトランザクション データです。データベースで実際の更新を行うには、多くのルックアップとデータ操作を行う必要があります。

私が抱えていると思われる問題は、データのクエリで、追跡された変更のキャッシュがいっぱいになることです。データの真のソースはデータベースでなければならないので、それは私には問題にならないようです。最終的にデータを変更して SaveChanges を呼び出すと、制約エラーが発生します。これが私の手順です。

  1. データを照会します。
  2. 挿入する行を作成します。
  3. 行を db と比較し、db を変更します。

Ctx.ChangeTracker.Entries() のデータを確認したところ、削除する予定のエントリが変更済みとしてマークされていることがわかりました。私がそれを回避した方法は、ステップ 3 の新しいコンテキストを作成することでした。そして、魔法のように機能し始めました。それだけだと思いましたが、私のテスト ケースでは、トランザクションが正しく書き込まれていることを確認するために、データベースから最後に読み取りを行います。そして、すでに削除されているはずの余分な行を取得していました。実際、データベースを直接チェックするときでした。最後の読み取りを行うための新しいコンテキストが問題を修正しました。

デフォルトのキャッシュ設定は変更を追跡するためだけに使用され、クエリを高速化するためではないと思いました。

クエリで AsNoTracking を使用しようとすると、そのようにクエリされた行を削除しようとするとエラーが発生するため、問題が発生します。そして、私のコードでは、後で削除するか変更するかはわかりません。新しいコンテキストを作成する必要がないようにキャッシュをクリアする方法はありますか?

これらの問題に対処するためのより良い方法はありますか?

編集:

AsNoTracking は、ある程度のトリックを行います。エラーを防ぐために、DbContext のコピーをさらにインスタンス化していることに気付きました。多対 1 のエンティティを順番に削除する必要があります。そうしないと、null 外部キー エラーがトリガーされます。

var details = oldInvoice.details.ToList();

Context.Entry(oldInvoice).State = EntityState.Unchanged;
Context.Entry(oldInvoice).State = EntityState.Deleted;
details.ForEach(a => Context.Entry(a).State = EntityState.Deleted);
4

1 に答える 1