現在のプロジェクトでは、WebAPIとEntityFrameworkモデル ファーストを使用しています。調査の結果、LazyLoading
関連エンティティをロードするために使用する必要があるようです。
サービスで使用するとパフォーマンスとシリアル化の問題が発生する可能性があることを多くのブログで読んだLazyLoading
ので、可能であれば避けたいと思います。
POCOオブジェクトを作成せずにこれを達成する方法について何か提案はありますか?
現在のプロジェクトでは、WebAPIとEntityFrameworkモデル ファーストを使用しています。調査の結果、LazyLoading
関連エンティティをロードするために使用する必要があるようです。
サービスで使用するとパフォーマンスとシリアル化の問題が発生する可能性があることを多くのブログで読んだLazyLoading
ので、可能であれば避けたいと思います。
POCOオブジェクトを作成せずにこれを達成する方法について何か提案はありますか?
あなたの質問に対する簡単な答えは - use.Include()
です。
例として、別の顧客を参照Customer
する関連付けられたオブジェクトを持つオブジェクトがあるとします。アプリケーションで、 のリストと、それぞれを紹介した関連人物ReferredBy
を返す必要があります。Customer
Customer
WebAPI メソッドは次のようになります。
[HttpGet]
public IQueryable<Customer> Customers() {
return db.Customers.OrderBy(c => c.LastName).Top(10);
}
シリアライザーがこれを把握すると、さまざまなエラーが発生する可能性があります。詳細については、この記事を参照してください。ただし、本質的には、次の 2 つのことから生じます。
A
を参照しB
、 をB
参照するA
ので、一方をシリアル化するたびに、もう一方をその子として再度シリアル化します。これにより、無限ループが作成されます。すべての詳細やその他の問題については説明しません。これについては、ある程度詳しく説明した記事を既に提供しています。代わりに、アプリケーションで問題を解決する方法を次に示します。
Global.asax
構成の一部としてロードされるファイルまたはファイルの 1 つで、.cs
次の設定を使用します。
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore;
これは、JSON.netに参照ループをシリアライズしないように指示します。
およびその各プロパティで を に設定MergeOption
します。私のアプリケーションでは、次のファイルを作成するファイルを編集してこれを行います。DataContext
Collection
MergeOption.NoTracking
.tt
DataContext
まず、コンストラクターを作成する行を見つけて、次のように変更します。
MergeOption _defaultMergeOption = MergeOption.AppendOnly;
public <#=code.Escape(container)#>() : this("name=<#=container.Name#>") { }
public <#=code.Escape(container)#>(String connectionString) : base(connectionString) {
<# if (!loader.IsLazyLoadingEnabled(container)) { #>
this.Configuration.LazyLoadingEnabled = false;
<# } #>
this.Configuration.ProxyCreationEnabled = false;
_defaultMergeOption = MergeOption.NoTracking;
}
次で始まる行を見つけます。
<# foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>()) { #>
次の数行を次のように編集します。
<# foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>()) { #>
<#= Accessibility.ForReadOnlyProperty(entitySet)#> ObjectQuery<<#=typeMapper.GetTypeName(entitySet.ElementType)#>> <#=code.Escape(entitySet)#> {
get {
var set = (((IObjectContextAdapter)this).ObjectContext).CreateObjectSet<<#=typeMapper.GetTypeName(entitySet.ElementType)#>>();
set.MergeOption = _defaultMergeOption;
return set;
}
}
<# }
DataContext
これが何をするかというと、すべてのコレクションを にデフォルト設定しMergeOption.NoTracking
、 と を自動的に無効にProxyCreation
するコンストラクタを提供することですLazyLoading
。プル元のインスタンスを作成するときはDataContext
、次のように簡単に言うことができます。
var db = new MyDataContext("ConnectionStringGoesHere");
上記を考えると、新しい WebAPI メソッドは次のように単純になります。
[HttpGet]
public IQueryable<Customer> Customers() {
return db.Customers.Include("ReferredBy")
.OrderBy(c => c.LastName).Top(10);
}
は.Include()
最初の SQL ステートメントの一部として子レコードをロードし (データベースへの合計 1 つのヒット)、シリアライザーは後方参照を無視するため、次のような JSON を生成できます。
[{
Id: 1,
FirstName: 'Frank',
LastName: 'Abba',
ReferredBy: {
Id: 4,
FirstName: 'Bob',
LastName: 'Jones',
ReferredBy: null
}
}, {
Id: 4,
FirstName: 'Bob',
LastName: 'Jones',
ReferredBy: null
}
}]