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

Entity framework 实体框架-什么';使用Include/eager加载和延迟加载之间的区别是什么?,entity-framework,lazy-loading,eager-loading,Entity Framework,Lazy Loading,Eager Loading,我一直在努力熟悉实体框架。大部分内容看起来都很简单,但我对Include方法和默认延迟加载之间的区别有点困惑。两者似乎都加载了相关的实体,因此表面上看起来它们做了相同的事情。我遗漏了什么?急切加载旨在解决ORMs特有的问题。简短的版本是这样的:如果您要直接检索一些实体,并且您知道您将通过检索到的实体访问某些相关实体,那么一次检索所有相关实体将更加高效,与通过延迟加载增量检索相比。假设您有两个具有一对多关系的实体:客户和订单,其中每个客户可以有多个订单 加载客户实体时,实体框架允许您快速加载或延迟

我一直在努力熟悉实体框架。大部分内容看起来都很简单,但我对Include方法和默认延迟加载之间的区别有点困惑。两者似乎都加载了相关的实体,因此表面上看起来它们做了相同的事情。我遗漏了什么?

急切加载旨在解决ORMs特有的问题。简短的版本是这样的:如果您要直接检索一些实体,并且您知道您将通过检索到的实体访问某些相关实体,那么一次检索所有相关实体将更加高效,与通过延迟加载增量检索相比。

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

加载客户实体时,实体框架允许您快速加载或延迟加载客户的订单集合。如果选择立即加载Orders集合,则当从数据库中检索客户时,实体框架将生成SQL,在一个查询中检索客户信息和客户订单。但是,如果选择延迟加载Orders集合,当从数据库中检索客户时,实体框架将生成仅提取客户信息的SQL(如果稍后在代码中访问客户的Orders集合,实体框架将生成单独的SQL语句)

确定何时使用即时加载和何时使用延迟加载都取决于您对所检索实体的期望。如果您知道您只需要客户的信息,那么您应该延迟加载Orders集合(这样SQL查询就可以通过只检索客户的信息来提高效率)。相反,如果您知道需要遍历客户的订单,那么您应该立即加载订单(这样,在代码中访问客户的订单后,您将为自己保存一个额外的数据库命中)


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

如果您来自SQL world,请考虑加入

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

1)延迟加载(=11 queryes=SLOW性能)

EF将发出一个查询以检索订单,并对每个订单发出一个查询以检索客户数据

Select * from order where order=1
+
10 x (Select * from customer where id = (order.customerId))
1)急切加载(=1查询=高性能)

EF将执行一个查询,通过联接检索订单和客户

Select * from orders INNER JOIN customers on orders.customerId=customer.Id where order=1
PS: 从数据库检索对象时,该对象将在上下文处于活动状态时存储在缓存中。
在我使用LAZY LOAD创建的示例中,如果所有10个订单都与同一客户相关,那么您将只看到2个查询,因为当您请求EF检索对象时,EF将检查该对象是否在缓存中,并且如果发现该对象,它将不会向DB触发另一个SQL查询。

一个重要问题是序列化。如果处理序列化对象,Microsoft建议不要使用默认的延迟加载。序列化导致调用所有相关属性,这可能会引发查询相关实体的连锁反应。如果您从控制器返回JSON数据,这一点就非常重要。JSON数据显然是序列化的。您可能希望通过Eager立即返回数据,或者在上下文中关闭懒散加载,并使用显式懒散加载。

您的响应不清楚。您不能使用即时加载来加载客户的一个查询以及与客户相关的所有订单。通过快速加载,您可以检索订单和相关客户。@Bugeo这对我来说已经足够清楚了。当然,我已经知道区别了。但在我看来,这仍然是它的工作方式。@Erik请阅读secon pharagraph。回答中有个错误。“数据库实体框架外的客户将生成在一次查询中检索客户信息和客户订单的SQL”为false。它将只检索一个订单,而不是所有订单。@Bugeo你确定吗?我还没有对它进行测试,但是我非常确定一个急切的加载将对Orders表执行一个左外部连接,以检索客户的所有订单。否则,即时加载就不值得了。我可以看到使用延迟加载的一个用例场景是,如果您正在加载包含BLOB数据的相关数据。您可能不希望一次加载所有这些内容。