entity frameworkLINQ查询包含()多个子实体
这可能是一个真正的元素问题,但是在编写跨越三个级别(或更多)的查询时包括多个子实体的最好方法是什么?
即我有4个表: Company
, Employee
, Employee_Car
和Employee_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(); ...