开发手册 欢迎您!
软件开发者资料库

Entity Framework - 延迟加载

Entity Framework延迟加载 - 从概述,体系结构,环境设置,数据库设置,数据模型,DbContext,类型,关系,生命周期,代码优先方法,模型第一方法,数据库第一方法,DEV方法,数据库操作,并发开始学习实体框架,事务,视图,索引,存储过程,断开连接的实体,表值函数,本机SQL,枚举支持,异步查询,持久性,投影查询,命令记录,命令拦截,空间数据类型,继承,迁移,渴望,懒惰,显式加载,验证,跟踪更改,彩色实体,第一个示例,数据注释,Fluent API,种子数据库,代码优先迁移,多个DbContext,嵌套实体类型。

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

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

  • 延迟加载几乎是默认加载.

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

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

  • 导航属性应定义为public,virtual.如果属性未定义为虚拟,则上下文 NOT 执行延迟加载.

以下是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: 4041ID: 2, Name: Meredith Alonso       Enrollment ID: 4, Course ID: 1045       Enrollment ID: 5, Course ID: 3141       Enrollment ID: 6, Course ID: 2021ID: 3, Name: Arturo Anand       Enrollment ID: 7, Course ID: 1050ID: 4, Name: Gytis Barzdukas       Enrollment ID: 8, Course ID: 1050       Enrollment ID: 9, Course ID: 4022ID: 5, Name: Yan Li       Enrollment ID: 10, Course ID: 4041ID: 6, Name: Peggy Justice       Enrollment ID: 11, Course ID: 1045ID: 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 AlexanderID: 2, Name: Meredith AlonsID: 3, Name: Arturo AnandID: 4, Name: Gytis BarzdukaID: 5, Name: Yan LiID: 6, Name: Peggy JusticeID: 7, Name: Laura NormanID: 8, Name: Nino Olivetto

我们建议您在一个步骤中执行上述示例为了更好地理解,逐步的方式.