实体框架 - 使用Include / eager加载和延迟加载之间的区别是什么?

eager-loading entity-framework lazy-loading

我一直在努力熟悉实体框架。大部分内容似乎很简单,但我对使用Include方法和默认延迟加载的急切加载之间的区别感到困惑。两者似乎都加载了相关的实体,所以从表面看它们看起来像是做同样的事情。我错过了什么?

一般承认的答案

假设您有两个具有一对多关系的实体:客户和订单,其中每个客户可以有多个订单。

在加载Customer实体时,Entity Framework允许您急切加载或延迟加载Customer's Orders集合。如果您选择贪婪加载订单采集,在获取客户从数据库的实体框架将生成SQL检索客户的信息和客户在一个查询订单两者 。但是,如果您选择延迟加载Orders集合,当您从数据库中检索客户时,Entity Framework将生成提取客户信息的SQL(如果您稍后访问Customer's Orders集合,Entity Framework将生成单独的SQL语句在你的代码中)。

确定何时使用预先加载以及何时使用延迟加载都归结为您希望对检索的实体执行的操作。如果您知道您只需要客户的信息,那么您应该延迟加载Orders集合(以便通过仅检索客户的信息来提高SQL查询的效率)。相反,如果您知道您需要遍历客户订单,那么您应该急于加载订单(这样一旦您访问代码中的客户订单,您就可以节省额外的数据库命中)。

PS使用延迟加载时要非常小心,因为它会导致N + 1问题。例如,假设您有一个显示客户及其订单列表的页面。但是,您在获取订单时决定使用延迟加载。当您遍历Customers集合,然后遍历每个客户订单时,您将为每个客户执行数据库命中,以便在其Orders集合中进行延迟加载。这意味着对于N个客户,您将拥有N + 1个数据库命中(1个数据库命中以加载所有客户,然后N个数据库命中以加载他们的每个订单)而不是仅仅1个数据库命中,如果您使用了预先加载(它会在一个查询中检索所有客户及其订单)。


热门答案

如果你来自SQL世界,请考虑加入。

如果您必须在网格中显示10个订单,并且下订单的客户有2个选择:

1)懒惰负荷(= 11个查询=慢速表现)

EF将拍摄查询以检索订单并查询每个订单以检索客户数据。

Select * from order where order=1
+
10 x (Select * from customer where id = (order.customerId))

1)EAGER LOAD(= 1查询=高性能)

EF将拍摄单个查询以通过JOIN检索订单和客户。

Select * from orders INNER JOIN customers on orders.customerId=customer.Id where order=1

PS:从db中检索对象时,对象在上下文处于活动状态时存储在缓存中。在我使用LAZY LOAD创建的示例中, 如果所有10个订单都与同一个客户相关,那么您将只看到2个查询,因为当您要求EF检索对象时,EF将检查对象是否在缓存中以及是否发现它不会向DB发送另一个SQL查询。




许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因
许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因