实体框架 – 延迟加载

实体框架 – 延迟加载


延迟加载是在第一次访问引用实体或实体的属性时自动从数据库加载实体或实体集合的过程。延迟加载意味着延迟加载相关数据,直到您特别请求它为止。

  • 使用 POCO 实体类型时,延迟加载是通过创建派生代理类型的实例,然后覆盖虚拟属性以添加加载钩子来实现的。

  • 延迟加载几乎是默认设置。

  • 如果您保留默认配置,并且没有在查询中明确告诉实体框架您想要延迟加载以外的其他内容,那么您将获得延迟加载。

  • 例如,当使用 Student 实体类时,将在第一次访问 Enrollments 导航属性时加载相关的 Enrollments。

  • 导航属性应定义为公共、虚拟。如果属性未定义为虚拟,则上下文不会进行延迟加载。

以下是包含 Enrollments 导航属性的 Student 类。

public partial class Student {

   public Student() {
      this.Enrollments = new HashSet<Enrollment>();
   }
	
   public int ID { get; set; }
   public string LastName { get; set; }
   public string FirstMidName { get; set; }
   public System.DateTime EnrollmentDate { get; set; }
	
   public virtual ICollection<Enrollment> Enrollments { get; set; }
}

让我们看一个简单的示例,其中首先从数据库加载学生列表,然后在您需要时加载特定学生的注册。

class Program {

   static void Main(string[] args) {

      using (var context = new UniContextEntities()) {

         //Loading students only
         IList<Student> students = context.Students.ToList<Student>();

         foreach (var student in students) {

            string name = student.FirstMidName + " " + student.LastName;
            Console.WriteLine("ID: {0}, Name: {1}", student.ID, name);
	
            foreach (var enrollment in student.Enrollments) {
               Console.WriteLine("Enrollment ID: {0}, Course ID: {1}", 
                  enrollment.EnrollmentID, enrollment.CourseID);
            }
         }

         Console.ReadKey();
      }
   }
}	

编译并执行上述代码后,您将收到以下输出。

ID: 1, Name: Ali Alexander
       Enrollment ID: 1, Course ID: 1050
       Enrollment ID: 2, Course ID: 4022
       Enrollment ID: 3, Course ID: 4041
ID: 2, Name: Meredith Alonso
       Enrollment ID: 4, Course ID: 1045
       Enrollment ID: 5, Course ID: 3141
       Enrollment ID: 6, Course ID: 2021
ID: 3, Name: Arturo Anand
       Enrollment ID: 7, Course ID: 1050
ID: 4, Name: Gytis Barzdukas
       Enrollment ID: 8, Course ID: 1050
       Enrollment ID: 9, Course ID: 4022
ID: 5, Name: Yan Li
       Enrollment ID: 10, Course ID: 4041
ID: 6, Name: Peggy Justice
       Enrollment ID: 11, Course ID: 1045
ID: 7, Name: Laura Norman
       Enrollment ID: 12, Course ID: 3141

关闭延迟加载

延迟加载和序列化不能很好地混合,如果您不小心,您最终可能会因为启用了延迟加载而查询整个数据库。在序列化实体之前关闭延迟加载是一个很好的做法。

关闭特定导航属性

可以通过将 Enrollments 属性设为非虚拟来关闭 Enrollments 集合的延迟加载,如下例所示。

public partial class Student { 

   public Student() { 
      this.Enrollments = new HashSet<Enrollment>(); 
   }
	
   public int ID { get; set; } 
   public string LastName { get; set; } 
   public string FirstMidName { get; set; } 
   public System.DateTime EnrollmentDate { get; set; }
	
   public ICollection<Enrollment> Enrollments { get; set; } 
}

为所有实体关闭

可以通过将 Configuration 属性上的标志设置为 false 来关闭上下文中所有实体的延迟加载,如下例所示。

public partial class UniContextEntities : DbContext { 

   public UniContextEntities(): base("name = UniContextEntities") {
      this.Configuration.LazyLoadingEnabled = false;
   }
	
   protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
      throw new UnintentionalCodeFirstException(); 
   } 
}

关闭延迟加载后,现在再次运行上述示例时,您将看到未加载 Enrollments,仅检索学生数据。

ID: 1, Name: Ali Alexander
ID: 2, Name: Meredith Alons
ID: 3, Name: Arturo Anand
ID: 4, Name: Gytis Barzduka
ID: 5, Name: Yan Li
ID: 6, Name: Peggy Justice
ID: 7, Name: Laura Norman
ID: 8, Name: Nino Olivetto

我们建议您逐步执行上述示例,以便更好地理解。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁