65

誰かがこの決定を下すのに役立ついくつかのアドバイスを提供したり、ブログ/記事を指摘したりすることができますか?プロキシは私にとって非常に異質なように見えます。私はそれらを使うことを躊躇しています。私は自分のモデルで仮想プロパティを使ってLazy Loadingを制御するのが好きですが、それは私が見ることができるすべての利点です。私のアプリケーションは単純なMVC Webアプリケーションであり、エンティティが変更された状態になったときのためのフックをコンテキストに結びつける必要はありません。エンティティフレームワーク4.1とMVC3で動的プロキシを有効または無効にする必要がありますか?

とにかく、ここに私の非常に限定された賛否両論があります。 '保存' または '更新' で

賛否

  • 、私は 'Apply'Changes'
  • 遅延ロードの設定は非常に簡単であるとのシームレスな取得します。

短所

  • が私のエンティティの前にプロキシを使用することはありません、これはただ自分自身と仲間のチーム メンバーのために不快なようだ アプローチの変化です。
  • デバッグするのが難しいです。
  • シリアライズ/デシリアライズを行う場合は、特別なコードが必要です
  • '保存'または '更新'の場合、プロキシはコンテキストから取得したオブジェクトと同じである必要があります。区別するために2つの異なるタイプがありますが、EFに動的プロキシの話なら
+5

+1 - シリアル化/デシリアライズの問題は苦痛です! – StuartLC

答えて

101

  • プロキシ遅延読み込みのためには、通常

変更追跡プロキシを変更トラッキングのための

  • プロキシ遅延ロードのプロキシとしても機能します。その逆は真実ではない。これは、変更追跡プロキシの要件が高いため、特にです。プロパティ - スカラープロパティ - はすべてvirtualである必要があります。遅延読み込みの場合は、ナビゲーションプロパティがvirtualであれば十分です。

    変更追跡プロキシは常にも遅延読み込みを活用することを可能にするという事実は、DbContextは、この設定フラグを持っている主な理由です:

    DbContext.Configuration.LazyLoadingEnabled 
    

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

    オプション...

    DbContext.Configuration.ProxyCreationEnabled 
    

    ...完全にプロキシ作成を無効にします - 変更の追跡や遅延ローディングのためにも。

    両方のフラグは、エンティティクラスが変更トラッキングまたは遅延ロードプロキシの作成要件を満たしている場合にのみ意味を持ちます。

    動的レイジーローディングプロキシの目的を知っています。だから、なぜ動的な変更追跡プロキシを使うべきですか?

    私が知っている唯一の理由は、のパフォーマンスです。しかし、これは非常に強い理由です。スナップショットベースのチェンジトラッキングとプロキシベースのチェンジトラッキングを比較すると、パフォーマンスの差が大きくなります。私の測定値から、50〜100のファクタは現実的です(スナップショットベースのチェンジトラッキングを使用して10000のエンティティに対して約1時間、変更トラッキングプロキシを有効にするためにすべてのプロパティを仮想化した後)。多くの(1000以上の)エンティティを処理して変更するアプリケーションがある場合、これは重要な要素になります。 Webアプリケーションで、Webリクエストの単一のエンティティに対して作成/変更/削除操作しかできない場合、この違いはそれほど重要ではありません。

    ほとんどすべての状況で、レイジーローディングプロキシを使用したくない場合、同じ目標を達成するためにeagerまたはexpliciteのローディングを利用することができます。プロキシベースのレイジーロードまたは非プロキシベースのExpliciteローディングのパフォーマンスは同じです。なぜなら、ナビゲーションプロパティがロードされたときに基本的に同じクエリが実行されるからです。だから、あなたは多くを失うことなく、遅延ロードプロキシなしで暮らすことができます。

    派生エンティティをEF 4.0で使用する以外は、多くのエンティティを処理するために妥当なパフォーマンスを望む場合(DbContextを使用すると禁止されているため、EF 4.1のオプションではありません)またはEntity Frameworkをまったく使用しません。

    編集(2012年5月)

    私はchange tracking proxiesが速くなったり、さらに悪いパフォーマンスのスナップショットベースの追跡に比べていない状況があることを学んできた一方。

    チェンジトラッキングプロキシを使用する場合、これらの複雑さのため、デフォルトではスナップショットベースのチェンジトラッキングを使用し、プロキシは慎重に(いくつかのテストを行った後で)高性能が必要な状況でのみ使用しますスナップショットベースの変更追跡よりも高速です。

  • +1

    @Slauma - 私はあなたがそれらの設定を即座に変更できるかどうかは分かりませんでした。 if(DisableProxy)を使用する { context.Configuration.ProxyCreationEnabled = false; context.Configuration.LazyLoadingEnabled = false; } '循環参照エラーを引き起こさずにこれらの動的プロキシを直列化できるようにすることができました。ありがとう! +1 –

    15

    Entity Framework 5を使用している場合は、Performance Considerationsの記事を必ず確認してください。 Sections 5 NoTracking Queriesおよび8 Loading Related Entitiesは、情報に基づいた決定を下すために必要な情報を提供します。乾杯。

    2

    私はプロキシを使用しないことをお勧めします。動的プロキシの作成は、実行時の型チェックに依存するコンポーネントの不具合を引き起こすか、複雑になります。

    Automapperは、実行時にエンティティがダイナミックに生成されたプロキシタイプを持ち、オートマッピングを設定するときに渡したタイプではなく、タイプミスマッチ/予期しないタイプのエラーを実行時にスローします。

    +1

    Automapperはまさに私がこれを検討し始めたことと、潜在的にダイナミック・プロキシを変えることの欠点となっていました。 – FRoZeN

    +0

    私は動的プロキシという概念全体を嫌うようになりました。まず、プロキシに関連する問題は実行時にのみ表示されます。多くの場合、生産には明白ではない条件が満たされています(これは多くの場合、テスターに​​よって失われます)。第2に、呼び出しコードはしばしばプロキシの存在と特別な必要性を認識しなければならないので、漏れた抽象である。私は以来、全体のコンセプトを放棄し、それを無効にし、デザインを更新しました。動的なプロキシは、頭の後ろに撮影する必要があります。 –

    +2

    友人は動的なプロキシを友人に使用させません。 –

    0

    動的プロキシにはいくつかの優れた機能がありますが、実際は奇妙で不明瞭なバグがたくさんあります。

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

    これにより、プロセスが実行されている間、すべてのオブジェクトがメモリ内に残りました。 AsNoTrackingを使用してプロキシを無効にして、プロセスが正常に動作し、メモリとパフォーマンスが正常なレベルに戻るようにしなければなりませんでした。プロキシもそれらを作成したコンテキストを参照し、エンティティの巨大なグラフを保持することができます。デバッグはほとんど不可能です。

    したがって、私はプロキシをグローバルに無効にし、コードを含んでいます。大規模なチームをコーディングしているときは、このような問題を短時間でデバッグすることは非常に危険であり、不可能です。

    変更の追跡は素晴らしいです、それはいくつかの場所での使用を正当化するかもしれません。 あなたが何をしているのか分からない限り、遅延読み込みはパフォーマンスと直列化で大きな問題になることがあります。私はいつも熱心な、または明示的な読み込みが好きです。

    0

    Automapper 4.2.1を使用してください。新しいバージョンはDynamicMapを持っていません

    var parents = parentsRepo.GetAll().ToList(); 
    Mapper.CreateMap<Parent,ParentDto>(); 
    var parentsDto = Mapper.DynamicMap<List<ParentDto>>(parents); 
    
    関連する問題