これは本当に初歩的な質問かもしれませんが、3 つのレベル (またはそれ以上) にまたがるクエリを作成するときに、複数の子エンティティを含めるための適切な方法は何でしょうか?
つまり、4つのテーブルがあります: Company
、、Employee
およびEmployee_Car
Employee_Country
会社は従業員と1:1の関係にあります。
従業員は、Employee_Car と Employee_Country の両方と 1:m の関係を持ちます。
4 つのテーブルすべてからデータを返すクエリを記述する場合、現在は次のように記述しています。
Company company = context.Companies
.Include("Employee.Employee_Car")
.Include("Employee.Employee_Country")
.FirstOrDefault(c => c.Id == companyID);
もっとエレガントな方法があるはずです。これは冗長で、ひどいSQLを生成します。
私はVS 2010でEF4を使用しています
ベストアンサー1
EFコア
中間関係がコレクション(つまり、元の「主題」を持つ1対多)である、1ナビゲーション以上離れた関係(例えば、孫または祖父母関係)のEager Loading関係の場合、EF Coreには新しい拡張メソッドがあります。.ThenInclude()
構文は次のようになります少し違う古い EF 4-6 構文:
using Microsoft.EntityFrameworkCore;
...
var company = context.Companies
.Include(co => co.Employees)
.ThenInclude(emp => emp.Employee_Car)
.Include(co => co.Employees)
.ThenInclude(emp => emp.Employee_Country)
いくつかのメモ付き
Employees.Employee_Car
上記(および)のとおりEmployees.Employee_Country
、中間子コレクションの2つ以上の子プロパティを含める必要がある場合は、繰り返す必要があります.Include
コレクションの各子に対するコレクションのナビゲーション。- 個人的には、あなたの正気を保つために、余分な「インデント」を残しておくことをお勧めします
.ThenInclude
。
元の主体と1:1(またはN:1)の中間者のシリアル化では、ドット構文もサポートされています。例:
var company = context.Companies
.Include(co => co.City.Country);
これは機能的には次のものと同等です:
var company = context.Companies
.Include(co => co.City)
.ThenInclude(ci => ci.Country);
しかし、EFCoreでは、サブジェクトと1:Nの関係にある中間要素を介して連鎖する「Select」を使用する古いEF4/6構文は、サポートされていませんつまり
var company = context.Companies
.Include(co => co.Employee.Select(emp => emp.Address));
通常は次のようなわかりにくいエラーが発生します
'System.IntPtr' インスタンスのシリアル化と逆シリアル化はサポートされていません
EF 4.1 から EF 6
そこには強く型付けされた.Include
Select
適切な深さに式を提供することで、必要な Eager Loading の深さを指定できます。
using System.Data.Entity; // NB!
var company = context.Companies
.Include(co => co.Employees.Select(emp => emp.Employee_Car))
.Include(co => co.Employees.Select(emp => emp.Employee_Country))
.FirstOrDefault(co => co.companyID == companyID);
生成されたSQLは決して直感的ではありませんが、十分なパフォーマンスを発揮しているようです。小さな例を載せました。GitHubはこちら