このAsNoTracking()
、DetectChanges()
、およびAutoDetectChangesEnabled
の概念を知ったのはごく最近のことです。 AsNoTracking()
を使用してEntity Framework経由でデータベースからレコードをフェッチすると、Entity Frameworkはそれらのレコードの変更を追跡せず、その場合、フェッチされたレコードのプロパティの更新は失敗します。
私の質問は、レコードがその方法でフェッチされる場合、DetectChanges()への自動呼び出しを無効にするか、または次のように設定して明示的に行う必要があるかどうかです。
Context.Configuration.AutoDetectChangesEnabled = false;
また、読み取り専用の目的で厳密にデータをフェッチしているときに両方のアクションが実行されると、パフォーマンスの面でどのような影響があるかを教えてください。
Context.Configuration.AutoDetectChangesEnabled = false;
Context.Set<T>().AsNoTracking();
また、DetectChanges()への自動呼び出しを無効にします
いいえ、ありません。ただし、AsNoTracking
とDetectChanges
は互いに関係がないことを理解する必要があります(EFの一部であることを除きます)。 AsNoTracking
でフェッチされたオブジェクトは、AutoDetectChangesが有効かどうかにかかわらず、決して変更検出されません。さらに、AsNoTracking
はDbSet
レベルで機能し、AutoDetectChangesEnabled
はコンテキストレベルで機能します。 DbSet
メソッドがコンテキスト全体に影響するのは悪いことです。
または、[設定
AutoDetectChangesEnabled
]を明示的に行う必要がある
まあ、AutoDetectChangesを無効にすべきではないでしょう。 もしあなたはそれをするあなたはあなたが何をしているのかを知らなければなりません。
両方のアクションが実行された場合、(パフォーマンスに関して)どのような影響がありますか
言ったように、それらは関連していません。どちらも独自の方法でパフォーマンスを向上させることができます。
AsNoTracking
は、読み取り専用データを取得したい場合に最適です。副作用はありません(例:その効果は明らかです)設定AutoDetectChangesEnabled = false
はDetectChanges
(多数になる可能性があります)の自動呼び出しを停止しますが、注意が必要な副作用があります。 Lerman&Millerの本からDbContext:
DetectChangesを呼び出す必要がある場合の作業は、表示されるほど簡単ではありません。 Entity Frameworkチームは、パフォーマンスの問題が発生している場合にのみ、手動でDetectChangesを呼び出すように切り替えることを強くお勧めします。また、コードのパフォーマンスが低いセクションに対してのみ自動DetectChangesをオプトアウトし、問題のセクションの実行が終了したら再度有効にすることをお勧めします。
_AutoDetectChangesEnabled = false
_を設定すると、パフォーマンスに大きな影響(つまり、10倍)が生じる可能性があることがわかりました。
背景:私たちのシステムは、変更検出プロキシを使用するEFモデルオブジェクトで完全に構成されています。つまり、すべてのDBフィールドとリレーショナルプロパティが仮想として宣言されています。また、比較的深く構造化されたオブジェクトモデルもあります。つまり、オブジェクトAにはオブジェクトBのセットが含まれ、オブジェクトBにはオブジェクトCのセットなどが含まれます。EF/ LINQクエリを介して重要でない(> 100)数のこれらのオブジェクトをインスタンス化するとコストがかかることがわかりました。たとえば、1つのケースでは、250のオブジェクトをインスタンス化するには約2秒かかりました。同じ構造をインスタンス化することも観察しましたが、代わりに匿名オブジェクトを使用すると約25ミリ秒必要でした。最後に、_AutoDetectChangesEnabled = false
_を設定すると、EFモデルオブジェクトをインスタンス化するクエリを使用できるようになり、マテリアライズは約25 msでした。
したがって、少なくとも私たちにとっては、falseに設定することで大きな利益が得られました。作業単位パターンを使用し、作業単位が読み取り専用かどうかを明示的に示します。読み取り専用の作業単位の場合、_AutoDetectChangesEnabled = false
_の設定はまったく変更されないため、完全に安全です。実際、私たちは最初のリリースから2年後にこの変更をシステムに追加しました(そのため、コードには既存の作業単位が多数ありました)。この変更によって何も破壊されず、パフォーマンスが大幅に向上しました。
また、AsNoTracking()
を試したところ、基本的にパフォーマンスがまったく向上しないことがわかりました。私が理解しているように、AsNoTracking()
を使用したクエリは、オブジェクトがIDマップに配置されないことを意味します。これにより、EFがオブジェクトをディスク内で複数回参照した場合、ディスクからオブジェクトを再フェッチします。コンテキスト(たとえば、異なるクエリ内)。したがって、AsNoTracking()
には潜在的なマイナス面があります。
実装の詳細: