實體框架 - 延遲載入



延遲載入是指在第一次訪問引用實體/實體集合的屬性時,自動從資料庫載入實體或實體集合的過程。延遲載入意味著延遲載入相關資料,直到您明確請求它。

  • 當使用POCO實體型別時,延遲載入是透過建立派生代理型別的例項,然後重寫虛擬屬性來新增載入掛鉤實現的。

  • 延遲載入幾乎是預設設定。

  • 如果您保留預設配置,並且在查詢中沒有明確告訴實體框架您想要延遲載入以外的其他內容,那麼您將獲得延遲載入。

  • 例如,當使用Student實體類時,相關的Enrollments將在第一次訪問Enrollments導航屬性時載入。

  • 導航屬性應定義為public,virtual。如果屬性未定義為virtual,則Context將**不會**執行延遲載入。

以下是包含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(); 
   } 
}

關閉延遲載入後,現在再次執行上述示例時,您將看到Enrollments未載入,僅檢索學生資料。

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

我們建議您逐步執行上述示例以更好地理解。

廣告
© . All rights reserved.