EF中延遲載入的那些事

world發表於2020-07-18

延遲載入又稱懶載入,通俗一點就是關聯了一個物件,不用的時候不去查這個物件,當呼叫的時候再組織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;
                }
            }
        }

 

相關文章