エンティティフレームワーク linq クエリ Include() 複数の子エンティティ 質問する

エンティティフレームワーク linq クエリ Include() 複数の子エンティティ 質問する

これは本当に初歩的な質問かもしれませんが、3 つのレベル (またはそれ以上) にまたがるクエリを作成するときに、複数の子エンティティを含めるための適切な方法は何でしょうか?

つまり、4つのテーブルがあります: Company、、EmployeeおよびEmployee_CarEmployee_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

そこには強く型付けされた.IncludeSelect適切な深さに式を提供することで、必要な 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はこちら

おすすめ記事