【问题标题】:Entity frame work lazy loading enabled meaning实体框架延迟加载启用的含义
【发布时间】:2016-06-30 20:22:30
【问题描述】:

我已从该网站阅读了有关延迟加载的信息。 Enable or disable LazyLoading

“如果我们请求启用 LazyLoading 的学生列表,数据提供者将从数据库中获取我们所有的学生,但在显式访问该属性之前不会加载每个 StudentAddress 属性。”

这句话说当我设置Lazy Loading Enabled = true时,相关数据将不会被加载。不过

List<Students> stdList = Datacontext.Students.ToList();

如果我设置延迟加载启用 = true,上面的代码会返回所有学生及其老师和地址。我在这里想念的重点是什么?请问有人能解释一下吗?

【问题讨论】:

  • LazyLoading 只是在引用数据时(以 linq 术语)加载数据,而不是将其预加载到对象上,无论它是否为输出。如果您说:foreach(var student in stdList){@stdList.Address.City},上面的示例将延迟加载地址。通常,请远离 LazyLoading,因为它可能会导致 n+1 的情况,即用请求轰炸您的数据库服务器。

标签: entity-framework lazy-loading


【解决方案1】:

无论您有什么设置,如果您使用.ToList(),它将“枚举可枚举”。这非常意义重大,这句话应该成为你的常识。

当使用.ToList() 时,会发生很多事情。枚举可枚举意味着上一组如何枚举集合现在被用于实际迭代集合并填充数据。这意味着之前的枚举器(在内部存储为表达式树)现在将从实体框架发送到您的 SQLProvider 工厂。然后将表达式树中的对象图转换为 SQL 并在服务器上执行查询,从而返回数据并填充您的列表。

如果你有这个IQueryable 枚举,那么延迟加载而不是使用ToList(),然后迭代手动加载集合中的每个元素,或者只加载集合中的部分元素。

一旦您返回了元素列表,延迟加载只会在有导航属性的情况下发挥作用。如果有相关属性,例如,如果您有发票并且您想从客户表中获取相关的客户信息。该关系最初不会显式返回,只会返回发票。因此,为了获取客户数据,您可以(当上下文仍然打开,即未处理)通过对象上的 .Customer 引用访问它,它会加载。相反,要在原始枚举期间加载所有客户,您可以在可查询对象上使用 .Include() 功能,然后告诉 sql 提供程序工厂在发出查询时使用连接。


在您的具体示例中,

List<Students> stdList = Datacontext.Students.ToList();

无论是否启用延迟加载,这实际上不会加载所有教师和地址。它只会加载学生。如果你想延迟加载一个教师,而 Datacontext 仍然没有被释放,你可以使用

var firstStudent = stdList.First();
var teacher = firstStudent.Teacher; 
//and at this point lazy loading will fetch the teacher 
//by issuing **another** query (round trip) to the database

只有启用延迟加载才能实现。


对此的替代方法是预先加载,包括教师和地址。应该是这样的

List<Students> stdList = Datacontext.Students
    .Include( s => s.Teacher )
    .Include( s => s.Address ).ToList();

然后,如果您稍后尝试访问教师,上下文可能会被释放,并且仍然可以访问,因为数据已经加载。

var firstStudent = stdList.First();
var teacher = firstStudent.Teacher; 
//and at this point the teacher was already 
//loaded and as a result no additional round trip is required

【讨论】:

    【解决方案2】:

    您是如何注意到使用调试器加载了属性的?如果是这样,那么你已经有了答案。使用调试器,您也可以访问该属性,因此,这也会触发延迟加载。

    这是如何工作的?

    如果您的实体meets 有这些要求,那么 EF 将为您的每个支持更改跟踪或延迟加载的实体创建一个代理类。这样,您只能在访问相关实体时加载相关实体。正如我之前解释的,调试器也会触发延迟加载。

    现在,小心延迟加载,一旦你的上下文被释放,当你试图访问相关属性之一时,你会得到一个异常。所以,我建议在这种情况下使用eager loading

    【讨论】:

    • 我应该设置 Lazy Loading Enabled = false 还是不使用急切加载?
    • 如果您要使用急切加载,那么禁用延迟加载可能是个好主意,我在我的项目中这样做,以强制我明确写出我想加载相关属性,但是您可以同时使用两者。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多