实体框架 - 延迟加载
延迟加载是指第一次访问引用实体的属性时,自动从数据库加载实体或实体集合的过程。延迟加载意味着延迟加载相关数据,直到您明确请求它为止。
使用 POCO 实体类型时,延迟加载是通过创建派生代理类型的实例,然后覆盖虚拟属性以添加加载挂钩来实现的。
延迟加载几乎是默认设置。
如果您保留默认配置,并且没有在查询中明确告诉 Entity Framework 您想要除延迟加载之外的其他内容,那么您将获得延迟加载。
例如,当使用 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(); } }
关闭延迟加载后,当您再次运行上述示例时,您将看到注册信息未被加载,并且仅检索了学生数据。
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
为了更好地理解,我们建议您逐步执行上述示例。