Include() 在 LINQ 中做了啥?
Posted
技术标签:
【中文标题】Include() 在 LINQ 中做了啥?【英文标题】:What does Include() do in LINQ?Include() 在 LINQ 中做了什么? 【发布时间】:2014-10-30 19:33:33 【问题描述】:我尝试进行大量研究,但我更像是一个 db 专家 - 所以即使 MSDN 中的解释对我来说也没有任何意义。谁能解释一下,并提供一些关于Include()
语句在SQL
查询中的作用的例子吗?
【问题讨论】:
【参考方案1】:假设您想获取所有客户的列表:
var customers = context.Customers.ToList();
让我们假设每个Customer
对象都引用了它的Orders
集合,并且每个Order
都引用了LineItems
,而LineItems
也可能引用了Product
。
如您所见,选择具有许多相关实体的***对象可能会导致查询需要从多个来源中提取数据。作为一项性能指标,Include()
允许您指明应从数据库中读取哪些相关实体作为同一查询的一部分。
使用相同的示例,这可能会引入所有相关的订单标题,但没有其他记录:
var customersWithOrderDetail = context.Customers.Include("Orders").ToList();
作为最后一点,因为您要求 SQL,第一个没有Include()
的语句可以生成一个简单的语句:
SELECT * FROM Customers;
调用Include("Orders")
的最终语句可能如下所示:
SELECT *
FROM Customers JOIN Orders ON Customers.Id = Orders.CustomerId;
【讨论】:
谢谢。使用您的示例,我可以说如果我还想包含LineItems
和Products
,LINQ 查询应该如下所示:var customersWithOrderDetail = context.Customers.Include("Orders").Include("LineItems").Include("Products").ToList();
?
是的,您可以将多个调用链接到Include()
以沿不同的“路径”捕获对象。如果您希望对象位于同一路径中,则只需进行一次调用即可指定整个路径。由于LineItems
和Products
不共享任何路径组件,因此您确实需要单独调用。
@Yuck 它是哪种类型的连接?
@Tk1993 当外键可以为空时它是Left Join
,当它不是时Inner Join
。
Join(...)
语法允许您指定用于join
的逻辑。 Include(...)
不会,并将根据配置的实体之间的关系构建join
语句。【参考方案2】:
我只是想补充一点,“包含”是急切加载的一部分。它在 Microsoft 的 Entity Framework 6 教程中进行了描述。链接在这里: https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/reading-related-data-with-the-entity-framework-in-an-asp-net-mvc-application
摘自链接页面:
实体框架可以通过以下几种方式将相关数据加载到实体的导航属性中:
延迟加载。第一次读取实体时,不会检索相关数据。但是,第一次尝试访问导航属性时,会自动检索该导航属性所需的数据。这会导致向数据库发送多个查询——一个针对实体本身的查询,以及每次必须检索实体的相关数据时的一个查询。 DbContext 类默认启用延迟加载。
急切加载。当实体被读取时,相关数据随之被检索。这通常会导致单个连接查询检索所需的所有数据。您可以使用
Include
方法指定预加载。显式加载。这类似于延迟加载,只是您在代码中显式检索相关数据;当您访问导航属性时,它不会自动发生。您可以通过获取实体的对象状态管理器条目并为集合调用 Collection.Load 方法或为包含单个实体的属性调用 Reference.Load 方法来手动加载相关数据。 (在下面的示例中,如果您想加载管理员导航属性,您需要将
Collection(x => x.Courses)
替换为Reference(x => x.Administrator)
。)通常,您只会在关闭延迟加载时使用显式加载。由于它们不会立即检索属性值,因此延迟加载和显式加载也称为延迟加载。
【讨论】:
【参考方案3】:可以将其视为在您的子项目将延迟加载的情况下强制执行 Eager-Loading。
EF 发送到数据库的查询一开始会产生较大的结果,但在访问时,访问包含的项目时不会进行后续查询。
另一方面,如果没有它,EF 会在您第一次访问子项时执行单独的查询。
【讨论】:
以上是关于Include() 在 LINQ 中做了啥?的主要内容,如果未能解决你的问题,请参考以下文章
nextState 在 shouldComponentUpdate 中做了啥?
elementFormDefault 在 XSD 中做了啥?