'Top'オブジェクトに0〜N 'Sub'オブジェクトがあるデータモデルがあります。 SQLでは、これは外部キーdbo.Sub.TopId
によって実現されます。EFコアネストされたLinq selectの結果がN + 1個のSQLクエリ
var query = context.Top
//.Include(t => t.Sub) Doesn't seem to do anything
.Select(t => new {
prop1 = t.C1,
prop2 = t.Sub.Select(s => new {
prop21 = s.C3 //C3 is a column in the table 'Sub'
})
//.ToArray() results in N + 1 queries
});
var res = query.ToArray();
。結果は完全にロードされるので、res[0].prop2
は既に埋め込まれたIEnumerable<SomeAnonymousType>
になります。
サブコレクションがまだロードされず、型であるがEntityFrameworkCore(NuGet v1.1.0デベロッパー)を使用して:
System.Linq.Enumerable.WhereSelectEnumerableIterator<Microsoft.EntityFrameworkCore.Storage.ValueBuffer, <>f__AnonymousType1<string>>.
をあなたはそれを反復処理するまでデータがN +で、その結果、ロードされません1クエリ。私が.ToArray()
をコメントに追加すると、データはvar res
に完全にロードされますが、SQLプロファイラを使用するとこれは1つのSQLクエリーでこれ以上達成されません。各 'Top'オブジェクトに対して、 'Sub'テーブルのクエリが実行されます。
最初に指定する.Include(t => t.Sub)
は何も変更されていないようです。匿名型の使用は問題ではないようですが、new { ... }
ブロックをnew MyPocoClass { ... }
に置き換えても何も変わりません。
私の質問はすべてのデータがすぐに読み込まれるEF6と同様の動作をする方法はありますか?
注:私はこの例では、問題はそうのようなクエリを実行後にメモリに匿名のオブジェクトを作成することによって固定することができますことを実現:
var query2 = context.Top
.Include(t => t.Sub)
.ToArray()
.Select(t => new //... select what is needed, fill anonymous types
しかしこれはただのですAutoMapperが私のプロジェクトでDTOを埋めるためにLinqクエリの一部になるオブジェクトの作成が実際に必要です。
更新:新しいEFコア2.0でテストしたところ、問題は残っています。 (21-08-2017)
問題がaspnet/EntityFrameworkCore
GitHubのレポで追跡されています。Issue 4007
更新:年以降では、この問題は、以下の私の答えを参照してください、バージョン2.1.0-preview1-final
で修正されています。 (01-03-2018)
レイジーローディングをどこで/どのようにオフにしていますか? –
遅延ロードはEF6に適用されます。私の質問はEFコアについてです。私が知る限り、コアには遅延ロードがありません。 – GWigWam
Ah、okidoke ...あなたが実行しようとしているインクルードは、クエリーが始まるタイプのエンティティインスタンスを返さないので無視されています。 –