最初にEFコードのCTP5に対してProxyCreationEnabledをオフにすることの欠点は何ですか


82

私のWCFサービスがコードファーストモデルからクラスを返すことができる唯一の方法は、以下のコードProxyCreationEnablefalse使用するようにを設定することです。

((IObjectContextAdapter)MyDb).ObjectContext.ContextOptions.ProxyCreationEnable = false;

これを行うことの悪影響は何ですか?1つの利点は、少なくともこれらの動的タイプをシリアル化して、WCFを使用してネットワーク経由で送信できることです。

回答:


71

動的プロキシは、変更の追跡と遅延読み込みに使用されます。WCFがオブジェクトをシリアル化しようとすると、通常、関連するコンテキストは閉じられて破棄されますが、ナビゲーションプロパティをシリアル化すると、(閉じたコンテキストで)遅延読み込みが自動的にトリガーされます=>例外。

遅延読み込みをオフにする場合は、使用するすべてのナビゲーションプロパティに積極的な読み込みを使用する必要があります(ObjectQueryに含める)。変更の追跡はWCFでは機能せず、ObjectContextにアタッチされているエンティティの変更に対してのみ機能します。


7
ProxyCreationEnabledを無効にすることでパフォーマンス上の利点はありますか?たとえば、積極的な読み込みで読み取りを行うためだけに、DbContextインスタンスを頻繁に取得します。
Chris Moschini 2013年

2
@ChrisMoschini "POCOエンティティに変更追跡プロキシがない場合、エンティティのコンテンツを以前に保存された状態のコピーと比較することで変更が検出されます。コンテキストに多数のエンティティがある場合、この詳細な比較は長いプロセスになります。 、またはエンティティに非常に大量のプロパティがある場合、最後の比較が行われてから変更されていない場合でも。」msdn.microsoft.com/en-us/library/hh949853(v=vs.113).aspx
Niklas Peter

75

DbContext.Configuration.ProxyCreationEnabledがに設定されている場合falseIncludeメソッドが親オブジェクトで呼び出されない限り、DbContextは一部の親オブジェクトの子オブジェクトをロードしません。設定DbContext.Configuration.LazyLoadingEnabledするtruefalse、その動作に影響を与えません。

DbContext.Configuration.ProxyCreationEnabledがに設定されている場合true、子オブジェクトは自動的にロードされ、DbContext.Configuration.LazyLoadingEnabledvalueは子オブジェクトがいつロードされるかを制御します。


10

EFを使用すると、デフォルトでクラスのプロキシが作成されます。解決策は、DbContextクラスのコンストラクターにこの行を追加することです。データモデルはDbContextクラスから継承されているため、次のようにモデルを編集できます。

    public yourDataModelEntities()
        : base("name=yourDataModelEntities")
    {
        base.Configuration.ProxyCreationEnabled = false;
    }

このクラスは、あなたの中にあるEF.edmx中で、その後yourmodel.Context.tt、その後yourmodel.Context.cs


2
これは答えではありませんが、とにかく助けになりました。
山本晃

1
その行を入れるプロセスを自動化する方法について良い提案がありますか?モデルを再作成するたびに、プロパティをfalseに設定するのを忘れることは間違いありません。そのため、誰かがモデルの何が問題になっているのかを理解するまでに、デバッグに数時間かかる場合があります。
Konrad Viltersten 2015

@ konrad-オーバーライドされないように、部分クラスでコードを作成します。 パブリック部分クラスyourDataMoldelEntities()
Mikee 2016

@Mikee本当に?自動生成されたコンストラクターが、部分クラスで私が作成したコンストラクターと衝突するため、何らかの問題が発生することが予想されます...
Konrad Viltersten 2016

@konrad彼らは、コードを上書きしない方法を提供するために、部分クラス「type」を作成しました
Mikee 2016

6

(Visual Studio 2013以降を使用)

データベースからモデルを更新するたびにEFモデルのクラスコンストラクターが編集されないようにするため、またはその他の方法でコードの再構築をトリガーするために、変更を行う適切な場所は、責任のあるT4コードファイルです。実際にモデルコードを作成します。数年前、クラスとプロパティが実際にどのように作成されたかの基礎となるメカニズムを理解したときに、動的プロパティに関する他の問題が発生しました。T4 !!! それはなんと奇跡なのでしょう:-DT4構文は最初は少し威圧的かもしれないので、構文を読むのは賢明です。変更を加えるときに非常に集中することも良い考えです:-)

そう!モデルを見ると、.edmxファイルの下に.ttファイルがあります。この.tt(T4)ファイルは、実際にモデルクラスを作成するスクリプトです。スクリプトは、モデルをビルドするか、モデルエディターで変更を加えるたびに自動的に実行されます。

モデル記述子の名前がModel1.edmxであるとします。その下のツリーにModel1.Context.ttという名前のファイルがあります。Model1.Context.csファイルも表示されます。これは明らかにあなたのコンテキストの実際のコードファイルです。ただし、このファイルは、実行されている.ttスクリプトファイルの結果です。完全に動的に作成されます。だからそれを編集する考えはありません。

.ttファイルを開くと、次のようなものが表示されます。

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF6.Utility.CS.ttinclude"#><#@
 output extension=".cs"#><#

const string inputFile = @"Model1.edmx";
var textTransform = DynamicTextTransformation.Create(this);
..
..

さらに50行ほど下がると、コンストラクターコードがスクリプト化されます。

using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
<#
if (container.FunctionImports.Any())
{
#>
using System.Data.Entity.Core.Objects;
using System.Linq;
<#
}
#>

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
    {
        public <#=code.Escape(container)#>()
            : base("name=<#=container.Name#>")
        {
        base.Configuration.ProxyCreationEnabled = false;
    <#
    if (!loader.IsLazyLoadingEnabled(container))
    {
    #>
            this.Configuration.LazyLoadingEnabled = false;
    <#
    }

base.Configuration.ProxyCreationEnabled = false;コンストラクターの最初の行になるようにプロパティを追加しました。

ファイルを保存し、Model1.Context.csファイルを開いて、結果のコードを確認します。テンプレートスクリプトを強制的に実行する場合は、メニューを選択します

ビルド-すべてのT4テンプレートを変換します

.csファイルはまったく作成されないか、エディターで開いた場合に明らかなエラーが発生するため、T4コードを間違えたかどうかを簡単に知ることができます。


うわー-これは根本的な問題を修正するので、本当に好ましい解決策になるはずです。また、*。ttファイルと結果の* .csファイルとの関係についての優れた背景情報も提供します。
ダグラスティムズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.