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系列教程彙總

相關文章
相關標籤/搜索