entity frameworkLINQ查询包含()多个子实体

这可能是一个真正的元素问题,但是在编写跨越三个级别(或更多)的查询时包括多个子实体的最好方法是什么?

即我有4个表: CompanyEmployeeEmployee_CarEmployee_Country

公司与员工有1:m的关系。

员工与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

使用扩展方法 。 将NameOfContextreplace为对象上下文的名称。

 public static class Extensions{ public static IQueryable<Company> CompleteCompanies(this NameOfContext context){ return context.Companies .Include("Employee.Employee_Car") .Include("Employee.Employee_Country") ; } public static Company CompanyById(this NameOfContext context, int companyID){ return context.Companies .Include("Employee.Employee_Car") .Include("Employee.Employee_Country") .FirstOrDefault(c => c.Id == companyID) ; } } 

那么你的代码变成了

  Company company = context.CompleteCompanies().FirstOrDefault(c => c.Id == companyID); //or if you want even more Company company = context.CompanyById(companyID); 

EF 4.1到EF 6

有一个强types的.Include它允许通过提供selectexpression式到适当的深度来指定所需的加载深度:

 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上放了一个小例子

EF核心

EF Core有一个新的扩展方法.ThenInclude() ,虽然语法略有不同 :

 var company = context.Companies .Include(co => co.Employees) .ThenInclude(emp => emp.Employee_Car) ... 

根据文档,我会保留额外的“缩进”。 .ThenInclude包括保持你的理智。

过时的信息(不要这样做):

多个孙子的加载可以一步完成,但是这需要一个相当尴尬的反转,在下一个节点之前备份graphics(注意:这不适用于AsNoTracking() – 你会得到一个运行时错误):

 var company = context.Companies .Include(co => co.Employees .Select(emp => emp.Employee_Car .Select(ec => ec.Employee) .Select(emp2 => emp2.Employee_Country))) .FirstOrDefault(co => co.companyID == companyID); 

所以我会留下第一个选项(一个包括每叶实体深度模型)。

您可能会在codeplex.com上find这篇感兴趣的文章。

  • 使用基于graphics的查询改进entity framework查询性能

本文提出了一种以声明graphicsforms表示跨多个表的查询的新方法。

而且,这篇文章包含了这个新方法与EF查询的全面性能比较。 这一分析表明GBQ快速超过EF查询。

如何构造一个LINQ to Entities查询来直接加载子对象,而不是调用Reference属性或Load()

没有其他的方法 – 除了实施延迟加载。

或者手动加载….

 myobj = context.MyObjects.First(); myobj.ChildA.Load(); myobj.ChildB.Load(); ...