我正在阅读this answer,并且我意识到我并不清楚在IQueryable
的内存生命周期中如何急切加载。
假设您有db.Customers.Include("Orders")
,它会生成如下对象图:
Customer
Order
Order
Order
如果您没有枚举来自Include
的回复,是否会将数据加载到内存中?
就是这样,
IQueryable<Customer> customersWithOrders = db.Customers.Include("Orders");
暗示Customer
集合(以及他的Orders
)已被热切包含的Orders
带入记忆中?或者,&#34;渴望&#34;意味着如果/ {枚举Customer
集合,订单也将被带入内存中?
答案 0 :(得分:2)
Eager Loading仅修改基础查询。这也是为什么你可以链接多个Include()
调用(以及依赖于LINQ的延迟执行特性的其他LINQ调用)的原因。
只有在枚举时才会从数据源明确请求数据。
更新(根据@Ehsan Sajjad评论):
使用延迟加载,即使查询已经实现(例如,使用foreach
或ToList()
),导航属性(在这种情况下为Order
)也只会在访问数据源时请求数据源。
答案 1 :(得分:2)
这里有两件事。首先,在完成需要执行该查询的某些操作之前,不会向数据库提交任何查询。例如,如果您要执行以下操作:
var foos = db.Foos.Where(...);
尚未发出任何查询。但是,如果你要这样做:
foreach (var foo in foos)
{
...
}
然后,查询被发送到数据库。导致查询执行的其他事情包括调用ToList()
,Count()
等。基本上,只要需要实际数据,那么,实体框架才会发送查询
然后,有一个完全独立的渴望与懒惰加载的概念。这是关于相关的项目,基本上是关于实体框架是否应该发出一个或多个连接作为查询的一部分。通过使用Include()
,您将指示实体框架为该关系发出连接。同样,在评估之前不会发出任何查询(迭代,枚举,计数等),但是当您对其进行评估时,您所包含的实体集和相关实体都将立即被拉出。
如果您选择不包含关系,那么您将回退到延迟加载,这意味着除非您以某种方式访问它,否则关系将不会实现。这在某些方面与初始查询的工作方式类似。仅在实际需要数据的位置获取相关项目;否则不发出查询。但是,这将是一个完全独立的查询。
长短,您只需要注意所需的数据和时间。如果您要使用相关实体,那么您应该在评估查询之前包含那些,但无论哪种方式,只有当它所代表的数据是必要时才会发送查询。