WCFサービスがコードファーストモデルからクラスを返すことができる唯一の方法は、以下のコードを使用してProxyCreationEnable
をfalse
に設定することです。
((IObjectContextAdapter)MyDb).ObjectContext.ContextOptions.ProxyCreationEnable = false;
これを行うことのマイナスの影響は何ですか? 1つの利点は、少なくともこれらの動的な型をシリアル化して、WCFを使用してネットワーク経由で送信できることです。
動的プロキシは、変更の追跡と遅延読み込みに使用されます。 WCFがオブジェクトをシリアル化しようとすると、通常、関連するコンテキストは閉じられて破棄されますが、ナビゲーションプロパティのシリアル化は、(閉じたコンテキストでの)遅延読み込み=>例外を自動的にトリガーします。
遅延読み込みをオフにした場合、使用するすべてのナビゲーションプロパティに積極的な読み込みを使用する必要があります(ObjectQueryに含める)。変更の追跡はWCF上では機能せず、ObjectContextにアタッチされているエンティティの変更に対してのみ機能します。
DbContext.Configuration.ProxyCreationEnabled
はfalse
に設定されます。親オブジェクトでInclude
メソッドが呼び出されない限り、DbContextは一部の親オブジェクトの子オブジェクトをロードしません。設定DbContext.Configuration.LazyLoadingEnabled
からtrue
またはfalse
は、その動作に影響を与えません。
DbContext.Configuration.ProxyCreationEnabled
はtrue
に設定され、子オブジェクトは自動的にロードされ、DbContext.Configuration.LazyLoadingEnabled
値は、子オブジェクトがロードされるタイミングを制御します。
EFを使用すると、デフォルトでクラスのプロキシが作成されます。解決策は、DbContextクラスのコンストラクターにこの行を追加することです。データモデルはDbContextクラスから継承されているため、次のようにモデルを編集できます。
public yourDataModelEntities()
: base("name=yourDataModelEntities")
{
base.Configuration.ProxyCreationEnabled = false;
}
このクラスはEF.edmx
その後、yourmodel.Context.tt
その後yourmodel.Context.cs
(Visual Studio 2013以降を使用)
データベースからモデルを更新するたびにEFモデルのクラスコンストラクターの編集を回避するため、またはその他の方法でコードの再構築をトリガーするために、変更を行う適切な場所は、T4コードファイル内にあります。実際にモデルコードを作成します。数年前、クラスとプロパティが実際にどのように作成されたのかという根本的なメカニズムを理解したときに、動的プロパティに関する他の問題がいくつかありました。 T4 !!!なんて奇跡なのか:-D T4構文は最初は少し怖いかもしれないので、構文を読むのは賢明です。変更を行うときに非常に集中することも良いアイデアです:-)
そう!モデルを見ると、.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コードでミスを犯したかどうかは簡単にわかります。