我已阅读本网站的延迟加载。 Enable or disable LazyLoading
"如果我们请求启用了LazyLoading的学生列表,数据提供者将从数据库中获取所有学生,但在明确访问该属性之前,不会加载每个StudentAddress属性。&#34 ;
此声明表示,当我设置Lazy Loading Enabled = true
时,相关数据将无法加载。然而
List<Students> stdList = Datacontext.Students.ToList();
如果我设置了延迟加载enabled = true,则上面的代码会返回所有的stundents及其老师和地址。我在这里失踪了什么?请有人解释一下吗?
答案 0 :(得分:1)
您是如何使用调试器注意到该属性已加载的?如果是这种情况,那么你已经有了答案。使用调试器也可以访问该属性,因此,这也会触发延迟加载。
这是如何运作的?
如果您的实体meets满足这些要求,那么EF将为您支持更改跟踪或延迟加载的每个实体创建代理类。这样,只有在访问相关实体时才能加载相关实体。正如我之前解释的那样,调试器也会触发延迟加载。
现在,请注意延迟加载,一旦处理了上下文,当您尝试访问其中一个相关属性时,将会出现异常。所以,我建议在这种情况下使用eager loading。
答案 1 :(得分:1)
无论您使用何种设置,如果您使用.ToList()
,它都会&#34;枚举可枚举的&#34;。这非常重要,这句话应该成为您的常识。
使用.ToList()
时会发生很多事情。枚举可枚举意味着前一组如何枚举该集合现在用于实际迭代该集合并填充数据。这意味着前一个枚举器(内部存储为表达式树)现在将从Entity Framework发送到您的SQLProvider Factory。然后,它会将对象图从表达式树转换为SQL并在服务器上执行查询,从而返回数据并填充列表。
延迟加载而不是使用ToList()
,如果你有这个IQueryable
可枚举,然后迭代手动加载集合中的每个元素,或者只是集合中的部分元素。
一旦返回了返回的元素列表,只有存在导航属性时才会进行延迟加载。如果存在相关属性,例如,如果您有发票,并且希望从客户表中获取相关的客户信息。首先不会明确返回关系,只会返回发票。因此,为了获得客户数据,您可以(当上下文仍处于打开状态,即未处理时)通过对象上的.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