68

誰かがアドバイスを提供したり、この決定を下すのに役立つ可能性のあるブログ/記事を指摘したりできますか?プロキシは私には非常に異質であるように思われ、私はそれらを使用することを躊躇しています。モデルの仮想プロパティを使用して遅延読み込みを制御する機能は気に入っていますが、それが私が見ることができるほとんどすべての利点です。私のアプリケーションは単純なMVCWebアプリケーションであり、エンティティが状態の変化を経験したときのために、コンテキストにフックを接続する必要はありません。

とにかく、これが私の今の長所と短所の非常に限られたリストです、私がこれのいずれかでベースから外れているかどうか私に知らせてください。

長所

  • 「保存」または「更新」では、「変更を適用」とシームレスになります
  • 遅延読み込みの構成は非常に簡単です。

短所

  • これまで私のエンティティにプロキシを使用したことはありませんでした。これはアプローチの変更であり、私自身や他のチームメンバーにとっては不快に思えます。
  • デバッグが面倒です。
  • シリアル化/逆シリアル化する場合は追加のコードが必要です
  • 「保存」または「更新」では、プロキシはコンテキストから取得されたものと同じオブジェクトである必要があります。
4

5 に答える 5

103

EF で動的プロキシについて話す場合、区別すべき 2 つの異なるタイプがあります。

  • 遅延読み込みのプロキシ
  • 変更追跡のプロキシ

通常、変更追跡プロキシは、遅延読み込みのプロキシとしても機能します。逆は当てはまりません。これは、変更追跡プロキシの要件が高く、特にすべてのプロパティ (スカラー プロパティも同様) が である必要があるためvirtualです。遅延読み込みの場合は、ナビゲーション プロパティが で十分ですvirtual

変更追跡プロキシが常に遅延読み込みを利用できるという事実が、DbContext にこの構成フラグがある主な理由です。

DbContext.Configuration.LazyLoadingEnabled

このフラグはデフォルトで true です。これを設定するとfalse、プロキシが作成されていても遅延読み込みが無効になります。これは、変更追跡プロキシを使用しているが、それらのプロキシを遅延読み込みにも使用したくない場合に特に重要です。

オプション ...

DbContext.Configuration.ProxyCreationEnabled

...プロキシの作成を完全に無効にします-変更の追跡と遅延読み込みも同様です。

どちらのフラグも、エンティティ クラスが変更追跡プロキシまたは遅延読み込みプロキシのいずれかを作成するための要件を満たしている場合にのみ意味を持ちます。

これで、動的な遅延読み込みプロキシの目的がわかりました。では、なぜ動的変更追跡プロキシを使用する必要があるのでしょうか?

実際、私が認識している唯一の理由はパフォーマンスです。しかし、これは非常に強力な理由です。スナップショット ベースの変更追跡とプロキシ ベースの変更追跡を比較すると、パフォーマンスの違いは非常に大きいです。私の測定では、50 倍から 100 倍が現実的です (スナップショット ベースの変更追跡で 10000 個のエンティティに対して約 1 時間、30 秒から 60 秒かかる方法から取得)。変更追跡プロキシを有効にするためにすべてのプロパティを仮想化した後)。多くの (たとえば 1000 以上の) エンティティを処理および変更するアプリケーションがある場合、これは重要な要素になります。Web 要求内の単一のエンティティに対して作成/変更/削除操作しかできない Web アプリケーションでは、この違いはそれほど重要ではありません。

ほとんどすべての状況で、遅延読み込みプロキシを使用したくない場合は、熱心な読み込みまたは明示的な読み込みを利用して同じ目標を達成できます。プロキシ ベースの遅延読み込みまたは非プロキシ ベースの明示的な読み込みのパフォーマンスは同じです。これは、ナビゲーション プロパティが読み込まれるときに基本的に同じクエリが発生するためです。最初のケースではプロキシがクエリを実行し、2 番目のケースでは手書きのコードが実行されます。そのため、遅延読み込みプロキシを使用せずに、大きな損失を被ることなく生活できます。

しかし、多くのエンティティを処理するために妥当なパフォーマンスが必要な場合は、変更追跡プロキシに代わるものはありませんEntityObject-EF 4.0 で派生エンティティを使用する (使用するときに禁止されているため、EF 4.1 ではオプションではありDbContextません) か、Entity Framework をまったく使用しないことを除いて.

編集 (2012 年 5 月)

その間、スナップショット ベースの追跡と比較して、変更追跡プロキシが高速ではない、またはパフォーマンスがさらに悪い状況があることを知りました。

変更追跡プロキシを使用する際のこれらの複雑さのため、推奨される方法は、デフォルトでスナップショット ベースの変更追跡を使用し、(いくつかのテストを行った後に) プロキシを慎重に使用することです (いくつかのテストを行った後)。追跡を変更します。

于 2011-08-18T18:44:04.837 に答える
15

Entity Framework 5 を使用している場合は、必ずパフォーマンスに関する考慮事項の記事を確認してください。十分な情報に基づいた決定を下すために必要な情報を提供しますSections 5 NoTracking Queries8 Loading Related Entities乾杯。

于 2012-10-11T23:09:58.100 に答える
2

プロキシを使用しないことをお勧めします。動的なプロキシの作成は、実行時の型チェックに依存するコンポーネントを中断または複雑化します。

たとえば、Automapper は、実行時に型の不一致 / 予期しない型のエラーをスローします。これは、自動マッピングの構成時に渡した型ではなく、実行時にエンティティが動的に生成されたプロキシ型を持つためです。

于 2015-09-24T14:25:04.040 に答える
0

動的プロキシにはいくつかの優れた機能がありますが、実際には多くの奇妙でわかりにくいバグを作成する可能性があります。

たとえば、私のクラスの 1 つでエンティティのプライベート変数を保持し (バッチ プロセスを実装していました)、数百万のレコードをループし、バッチで処理して挿入し、n レコードごとにデータ コンテキストを再作成して、メモリをクリーニングします。私はプライベート変数を使用したことはありませんが、EF はそれを私の新しいオブジェクトにリンクしていました (ナビゲーション プロパティを介した参照がありました)。

これにより、プロセスが実行されている間ずっと、すべてのオブジェクトがメモリに残っていました。プロセスが期待どおりに機能し、メモリとパフォーマンスが通常のレベルに戻るようにするには、AsNoTracking を使用してプロキシを無効にする必要がありました。プロキシはそれらを作成したコンテキストも参照することに注意してください。これにより、エンティティの巨大なグラフがメモリに保持される可能性があり、デバッグすることはほとんど不可能です。

したがって、プロキシをグローバルに無効にし、小さく含まれたコードで有効にする必要があると思います。特に大規模なチームでコーディングしている場合、このような問題をデバッグすることは非常に危険で不可能です。

変更の追跡は素晴らしいです。いくつかの場所での使用が正当化されるかもしれません。遅延読み込みは、自分が何をしているのかわからない限り、パフォーマンスとシリアライゼーションにおいて大きな問題になる可能性があります。私は常に積極的または明示的な読み込みを好みます。

于 2016-06-08T13:43:25.960 に答える