我已禁用延迟加载,但在访问引用实体/实体的属性时,会自动从数据库加载实体。为什么?它应该不再可访问了吗?
My EF version="6.1.3"
以下行加载部门数据,而我期望它不应该因为我已禁用延迟加载而且导航属性是非虚拟的。
Student student = context.Student.select(x => x.Department).First();
类:
public class Student
{
public string Name { get; set;}
public string Age { get; set;}
public string Date { get; set;}
public Department department { get; set }
}
public class Department
{
public string Id { get; set; }
public class Name { get; set; }
public Student Student { get; set }
}
上下文
public StudentContext : DbContext
{
public StudentContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
答案 0 :(得分:3)
什么是延迟加载?
通过在之后执行单独的数据库查询来加载相关数据的能力 执行了一些初始SQL查询并加载了一些实体。
首先让我们回顾一下你的课程:
考虑到这些,您将获得以下课程:
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public string Age { get; set; }
public string Date { get; set; }
public virtual Department Department { get; set; }
}
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
现在让我们看看启用延迟加载时会发生什么。例如。你正在加载学生:
Student bob = context.Students.FirstOrDefault(s => s.Name == "Bob");
这将产生类似于
的查询SELECT TOP(1) Name, Age, Date, Department_Id
FROM Students
WHERE Name = 'Bob' --actually name will be passed as query parameter
更重要的是,SQL查询将被执行,服务器的响应将被加载到内存中并映射到Student
实体。除了ID之外没有任何与部门相关的内容。现在,如果您尝试获取部门详细信息
var departmentName = bob.Department?.Name;
EF将生成SQL查询以加载相关的部门详细信息。像
这样的东西 SELECT d.Id, d.Name
FROM Students s
INNER JOIN Departments d ON s.Department_Id = d.Id
WHERE s.Id = 42 -- assume Bob has this id
此查询将被执行。这是服务器的第二次往返。这就是懒惰加载的方式。
当延迟加载被禁用时,将不会对服务器进行第二次查询。您将只拥有首次查询时加载的数据。即部门实体将为null
,您将无法获得该名称。
现在你的情况 - 你是通过第一次查询加载部门数据。实际上你的代码不会编译,因为你应该使用Department
实体:
Department dep = context.Student.Select(x => x.Department).First();
启用或禁用延迟加载不会影响延迟加载。因为正如我刚才写的那样,延迟加载会影响进一步加载相关数据的查询。但首先不是加载初始数据的查询。在你的情况下,它看起来像
SELECT TOP(1) d.Id, d.Name
FROM Students s
LEFT OUTER JOIN Departments d ON s.Department_Id = d.Id
答案 1 :(得分:2)
你对“延迟加载”的含义有错误的想法。
context.Student.Select(x => x.Department).First();
您明确要求Department
。 EF将履行该要求。您的查询没有任何“懒惰”:您明确要求Department
。
是的,您通过导航属性请求Department
,但这并不重要,因为您没有使用Student
的实例。 您正在直接向数据库发出查询。
您现在拥有Department
。延迟加载现在开始发挥作用,因为你已完成显式查询。
该部门有一个儿童财产,Student
。由于禁用了延迟加载,因此即使数据库中存在数据,此属性也将为null。如果引用该属性,它将为null,因为延迟加载被禁用 - EF不会自动为您获取数据。您必须明确查询该属性。
好的,所以说明确请求一个Student
对象。它的Department
属性将为null,因为禁用了延迟加载。引用该属性不会导致它被加载。您必须明确查询该属性。