Entity Framework入门教程(8)---预先加载、延迟加载、显示加载

1.预先加载

预先加载:在对一种类型的实体进行查询时,将相关的实体做为查询的一部分一块儿加载。预先加载能够使用Include()方法实现。html

1.加载一个相关实体类型

栗子:使用Include()方法从数据库中获取全部学生及成绩级别。
导航属性实现预先加载:sql

using (var ctx = new SchoolDBEntities())
{
  var stud1 = ctx.Students
          .Include("Standard")
          .Where(s => s.StudentName == "Bill")
          .FirstOrDefault<Student>();
}

lambda表达式实现预先加载:数据库

using (var ctx = new SchoolDBEntities())
{
  var stud1 = ctx.Students.Include(s => s.Standard)
          .Where(s => s.StudentName == "Bill")
          .FirstOrDefault<Student>();
}

2.加载多个相关实体类型

栗子:使用Include()方法从数据库中获取全部学生及其成绩级别和评分老师。
导航属性实现预先加载:ide

using (var ctx = new SchoolDBEntities())
{
    var stud1 = ctx.Students.Include("Standard.Teachers")
                .Where(s => s.StudentName == "Bill")
             .FirstOrDefault<Student>();
}                

lambda表达式实现预先加载:post

using (var ctx = new SchoolDBEntities())
{
  var stud1 = ctx.Students.Include(s => s.Standard.Teachers)
                .Where(s => s.StudentName == "Bill")
                .FirstOrDefault<Student>();
}

2.延迟加载

1.概念

延迟加载顾名思义就是不当即加载,而是在咱们访问的时候才加载,这和预先加载恰好相反。
一个栗子:查询Student的StudentAddressui

using (var ctx = new SchoolDBEntities())
{
    //这里只加载student实体,导航属性StudentAddress没有加载
  IList<Student> studList = ctx.Students.ToList<Student>();
  Student std = studList[0];

  //只加载特定student的住址(经过一个单独的sql进行实现的)
  StudentAddress add = std.StudentAddress;
}

2.禁用延迟加载

咱们能够禁用特定实体或者特定context的延迟加载。去掉实体导航属性的virtual,实体就不能进行延迟加载了。也能够经过context的cofiguration实现禁用该context下全部实体的延迟加载,代码以下:this

public partial class SchoolDBEntities : DbContext
{
    public SchoolDBEntities(): base("name=SchoolDBEntities")
    {    
        //SchoolDBEntities的全部实体都禁用延迟加载
    this.Configuration.LazyLoadingEnabled = false;
  }
  //若是去掉virtual那么Students禁用延迟加载
  public virtual DbSet<Student> Students { get; set; }
  protected override void OnModelCreating(DbModelBuilder modelBuilder){}
}

3.延迟加载前提

若是要实现延迟加载,必须知足下边三个条件,缺一不可spa

1.context.Configuration.ProxyCreationEnabled应为true。
2.context.Configuration.LazyLoadingEnabled应为true。
3.导航属性应定义为public virtual xxx,若是属性未定义为virtual,则Context不会进行延迟加载。

3.显式加载

1.Load方法

即便禁用了延迟加载(在EF 6中),仍然可能延迟加载相关实体,这时能够使用Load()方法显式加载相关实体。
一个栗子:code

using (var context = new SchoolContext())
{
  var student = context.Students
              .Where(s => s.FirstName == "Bill")
              .FirstOrDefault<Student>();

  context.Entry(student).Reference(s => s.StudentAddress).Load(); // loads StudentAddress
  context.Entry(student).Collection(s => s.StudentCourses).Load(); // loads Courses collection 
} 

在上面的栗子中, context.Entry(student).Reference(s => s.StudentAddress).Load() 会加载StudentAddress实体。Reference()方法用于获取指定实体导航属性的对象,Load()方法显式加载。htm

一样的方式, context.Entry(student).Collection(s => s.Courses).Load() Collection()加载student的集合导航属性Courses,Load()方法显示加载。

2.Query方法

有时候咱们想对查询的结果在加载前进行过滤,Query()方法就能够排上用场了。
一个栗子:查询名字为bill的学生的课程集合中数学课。

using (var context = new SchoolContext())
{
  var student = context.Students
              .Where(s => s.FirstName == "Bill")
              .FirstOrDefault<Student>();

  context.Entry(student)
      .Collection(s => s.StudentCourses)
      .Query()//这里不加载,下面对这一步的结果过滤
        .Where(sc => sc.CourseName == "Maths")
        .FirstOrDefault();
} 

在上边栗子中 .Collection(s => s.StudentCourses).Query() 不加载结果集,咱们能够把Query()方法的结果看做是一个中间结果,能够对中间结果作进一步过滤。

 

EF系列目录连接:Entity Franmework系列教程汇总