无论您有什么设置,如果您使用.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