📜  Entity Framework-延迟加载

📅  最后修改于: 2020-11-21 07:28:48             🧑  作者: Mango


延迟加载是这样的过程:首次访问引用一个或多个实体的属性时,将从数据库自动加载一个实体或一组实体。延迟加载意味着延迟相关数据的加载,直到您明确要求为止。

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

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

  • 如果您保留默认配置,并且没有在查询中明确告诉Entity Framework您需要除延迟加载以外的其他功能,那么延迟加载就是您将获得的。

  • 例如,当使用Student实体类时,相关的注册将在首次访问“注册”导航属性时加载。

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

以下是一个Student类,其中包含Enrollments的导航属性。

public partial class Student {

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

让我们看一个简单的示例,在该示例中,首先从数据库中加载学生名单,然后在需要时加载特定学生的入学申请。

class Program {

   static void Main(string[] args) {

      using (var context = new UniContextEntities()) {

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

         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(); 
   }
    
   public int ID { get; set; } 
   public string LastName { get; set; } 
   public string FirstMidName { get; set; } 
   public System.DateTime EnrollmentDate { get; set; }
    
   public ICollection 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(); 
   } 
}

关闭延迟加载后,现在当您再次运行以上示例时,您将看到未加载注册并且仅检索学生数据。

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

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