实体框架延迟加载启用的含义

Entity frame work lazy loading enabled meaning

我已从该网站了解延迟加载。 Enable or disable LazyLoading

"If we request a list of Students with LazyLoading enabled, the data provider will get all of our students from the DB but each StudentAddress property won’t be loaded until the property will be explicitly accessed."

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

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

如果我设置延迟加载启用 = true 上面的代码 returns 所有学生及其老师和地址。我在这里缺少的重点是什么?请问有人可以解释一下吗?

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

这是如何工作的?

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

现在,请小心延迟加载,一旦处理了上下文,当您尝试访问其中一个相关属性时,您将遇到异常。所以,我建议在这种情况下使用 eager loading

无论您有什么设置,如果您使用 .ToList(),它将 "enumerate the enumerable"。这非常重要,这句话应该成为您的常识。

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

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

返回元素列表后,延迟加载只有在具有导航属性时才会发挥作用。如果有相关的属性,比如你有一张发票,你想从客户table那里得到相关的客户信息。最初不会明确返回关系,只会返回发票。因此,为了获取客户数据,您可以(在上下文仍处于打开状态时,即未处理)通过对象上的 .Customer 引用访问它,它会加载。相反,要在原始枚举期间加载所有客户,您可以在可查询对象上使用 .Include() 功能,然后这会告诉 sql 提供程序工厂在发出查询时使用连接。


在您的具体示例中,

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

这实际上不会加载所有教师和地址,无论是否启用延迟加载。它只会加载学生。如果你想 延迟加载 一个 Teacher,而 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