已禁用延迟加载仍会加载相关实体。为什么呢?

时间:2017-03-27 16:30:12

标签: c# entity-framework

我已禁用延迟加载,但在访问引用实体/实体的属性时,会自动从数据库加载实体。为什么?它应该不再可访问了吗?

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;

    }

}

2 个答案:

答案 0 :(得分:3)

什么是延迟加载?

  

通过在之后执行单独的数据库查询来加载相关数据的能力   执行了一些初始SQL查询并加载了一些实体。

首先让我们回顾一下你的课程:

  • 与学生的关系不是1:1。每个部门都可以包含很多学生
  • 学生没有身份证明属性
  • 部门应该有整数ID
  • 为了支持延迟加载,导航属性应该是虚拟

考虑到这些,您将获得以下课程:

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,因为禁用了延迟加载。引用该属性不会导致它被加载。您必须明确查询该属性。