实体框架linq查询包含()多个子实体
这可能是一个真正的元素问题,但是在编写跨越三个级别(或更多)的查询时包含多个子实体的最好方法是什么?实体框架linq查询包含()多个子实体
即我有4个表:Company
,Employee
,Employee_Car
和Employee_Country
公司具有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
我使用EF4 VS 2010中
使用extension methods。 用您的对象上下文的名称替换NameOfContext。
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);
有没有其他办法 - 除了执行延迟加载。
或手动加载....
myobj = context.MyObjects.First();
myobj.ChildA.Load();
myobj.ChildB.Load();
...
您可能会发现这篇文章的兴趣是可以在codeplex.com。
本文提出了一种表达查询的新方法,该方式以声明图形形式跨越多个表。
此外,该文章包含了这种新方法与EF查询的全面性能比较。该分析表明GBQ快速超过EF查询。
非常有趣的文章! – 2015-04-27 07:46:55
EF 4.1至EF 6
有一个strongly typed .Include
其允许立即加载的所需的深度,以通过向适当的深度提供选择表达式来指定:
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 here
EF核心
EF核心有一个新的扩展方法,.ThenInclude()
,虽然语法是slightly different:
var company = context.Companies
.Include(co => co.Employees)
.ThenInclude(emp => emp.Employee_Car)
...
按的文档,我将保留额外的'缩进'.ThenInclude
以保持您的理智。
过时的信息(别这样做):
的多个孙子加载可以在一个步骤中完成,但是这需要一个比较尴尬的逆转回升图表标题下的下一个节点之前(注:这不会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);
所以我会留在第一个选项(每叶实体深度模型一个包含)。
我想知道如何用强类型.Include语句来完成它。用Select来展示孩子就是答案! – 2015-05-13 13:19:13
感谢您添加命名空间! – GRGodoi 2016-07-04 20:04:38
我的“co.Employees.Select(...)”等号在“Select”中显示语法错误,并说“'Employees'不包含'Select'[或扩展方法]的定义”。我已经包含了System.Data.Entity。我只想从连接表中获取单个列。 – 2017-01-17 09:55:31
这太棒了。 – 2013-03-20 18:32:17
但我想用它这个像:'//内公共静态类扩展 公共静态的IQueryable CompleteCompanies(这DbSet 表){ 返回表 .INCLUDE(“Employee.Employee_Car”) .INCLUDE(” Employee.Employee_Country“); } // code将... Company company = context.Companies.CompleteCompanies()。FirstOrDefault(c => c.Id == companyID); //下一个高级方法相同 –
Hamid
2016-03-28 08:28:20
Bullsye Nix。扩展应该是...的第一个端口,以及扩展预定义的功能。 – ComeIn 2016-04-23 10:29:21