1. 程式人生 > 實用技巧 >EF中延遲載入的那些事

EF中延遲載入的那些事

延遲載入又稱懶載入,通俗一點就是關聯了一個物件,不用的時候不去查這個物件,當呼叫的時候再組織sql去查出這個物件的相關內容。

一.在使用EF時,我們會發現藉助於框架生成的實體類中的的導航屬性通常是標記virtual的,這是為何呢?

二.讓我們通過幾個例子來發現其中的奧祕

下面的程式碼是通用的查詢,先是列印了查詢生成的sql,接著查詢出一個Employee物件並帶出對應的Dempartment物件。

       using (DemoEntities db = new DemoEntities())
{
db.Database.Log = sql => Console.WriteLine(sql);
Employee emp = db.Employees.FirstOrDefault();
Console.WriteLine(emp.Name);
Console.WriteLine(emp.Department.Name);
}

1.導航屬性上有virtual的情況下查詢兩條sql,一條是查出Employee另一條是查Dempartment

2.現在我們將預設的導航屬性中的virtual去掉會發生什麼呢,讓我們帶著疑惑繼續往下看

三.原理探究

看到這是不是感覺很怪異嘍,加上virtual就能正常執行,去掉就不行了麼。這是啥原理呢

1.我們把程式碼修改一下

     using (DemoEntities db = new DemoEntities())
{
Employee emp = db.Employees.FirstOrDefault();
Console.WriteLine(emp.GetType()); //列印emp的型別
Console.WriteLine(emp.GetType().BaseType); //列印emp型別對應的父類
Console.WriteLine(emp.Name);
Console.WriteLine(emp.Department.Name);
}

在原有的基礎上我們列印了一下對應物件的型別

2.我們還是先看看預設有virtual的情況

通過執行程式碼我們發現,我們所宣告的Employee的物件的型別竟然不是Employee而是一個名字特別長的另一個物件,而這個物件的父類才是Employee

3.我們將導航屬性的virtual去掉再執行程式碼看看有什麼變化

看到這裡的差異,我們似乎發現了點什麼。先說說virtual關鍵字吧,virtual是虛方法,通常是用於子類的重寫。那麼這裡我們不難推測當導航屬性有virtual關鍵字時,EF幫我們生成了一個

父類是Employee名字老長老長的那個類,在這個類的實現中,重寫了一下,當Department為空時,它會去資料庫裡查一下這個Department物件,所以加上virtual關鍵字時就會對應兩條sql

類似效果如下所示

    class Employee_515EB7DF3C6168BFE9566BD863543E3AED9398AFF473BAB129D9B32823D6E8A3 : Employee {
private Department _department;
public override Department Department
{
get
{
if (_department==null)
{
//去資料庫中查詢Department的資訊
}
return _department;
}
}
}