EF 延遲載入和預先載入

2021-09-07 08:07:04 字數 3610 閱讀 3832

最近悟出來乙個道理,在這兒分享給大家:學歷代表你的過去,能力代表你的現在,學習代表你的將來。

十年河東十年河西,莫欺少年窮

學無止境,精益求精

本節**延遲載入和預先載入

entity framework作為乙個優秀的orm框架,它使得運算元據庫就像操作記憶體中的資料一樣,但是這種抽象是有效能代價的,故魚和熊掌不能兼得。但是,通過對ef的學習,可以避免不必要的效能損失。本篇只介紹關聯實體的載入的相關知識,這在我之前的文章中都有介紹。

我們已經了解到ef的關聯實體載入有三種方式:lazy loading,eager loading,explicit loading,其中lazy loading和explicit loading都是延遲載入。eager loading是預先載入

延遲載入(lazy loading)。當實體第一次被讀取時,相關資料不會被獲取。但是,當你第一次嘗試訪問導航屬性時,該導航屬性所需的資料會自動載入。結果會使用多個查詢傳送到資料庫——一次是讀取實體本身,然後是每個相關的實體。dbcontext類預設是使用延遲載入的。

使用延遲載入必須滿足以下兩個條件

1、類是由public修飾,不能是封閉類,也就是說,不能帶有sealded修飾符

2、導航屬性標記為virtual。

如下 score 模型滿足了延遲載入的兩個條件

public

class

score

public

int studentscore //

學生分數

public

int studentid //

學生id

public

int courseid //

課程id

public

virtual student student //

virtual關鍵字修飾,用於延遲載入 提高效能 只有顯式呼叫時 才會載入 並可以代表乙個student物件 也就是 屬性==物件

public

virtual course course //

virtual關鍵字修飾,用於延遲載入 提高效能 只有顯式呼叫時 才會載入 並可以代表乙個course物件 也就是 屬性==物件

}

如果您不想使用延遲載入,您可以關閉lazy loading,將lazyloadingenabled設為false,如果導航屬性沒有標記為virtual,lazy loading也是不起作用的。

public

studentcontext()

: base("

studentcontext

")//

指定連線字串

(一)延遲載入

延遲載入就是資料不會一次性查出來,而是一條一條的查詢,這樣就會多次請求資料庫進行查詢,增加了資料庫的負擔。如果您的資料量打太大,建議使用預先載入,如果兩張表資料量很大,建議使用延遲載入。

public

actionresult linqtosql()

}return

view();

}

(二)預先載入使用include方法關聯預先載入的實體。

注:需引入:using system.data.entity;命名空間

預先載入就是從資料庫中一次性查詢所有資料,存放到記憶體中。如下方法採用預先載入

public

actionresult linqtosql()

return

view();

}

上述**就是將score表和student表左連線,然後查詢學生成績在80分以上的資訊。include()是立即查詢的,像tolist()一樣,不會稍後延遲優化後再載入。

如果兩張表記錄很大(欄位多,上百萬條記錄),採用include()關聯兩張表效率會很低,因為:它除了要做笛卡爾積,還要把資料一次性查詢出來。因此:在字段多,記錄多的情況下,建議使用延遲載入。

在此需要說明的是:ef中有兩種表關聯的方法,一種是join()方法,一種是include()方法

join()方法使用說明:兩表不必含有外來鍵關係,需要**手動指定連線外來鍵相等(具有可拓展性,除了值相等,還能指定是》,《以及其他對兩表的相應鍵的關係),以及結果字段。

include()方法說明:兩表必須含有外來鍵關係,只需要指定鍵名對應的類屬性名即可,不需指定結果字段(即全部對映)。預設搜尋某錶時,不會順帶查詢外來鍵表,直到真正使用時才會再讀取資料庫查詢;若是使用 include(),則會在讀取本表時把指定的外來鍵表資訊也讀出來。

(三)顯式載入有點類似於延遲載入,只是你在**中顯式地獲取相關資料。當您訪問乙個導航屬性時,它不會自動載入。你需要通過使用實體的物件狀態管理器並呼叫集合上的collection.load方法或通過持有單個實體的屬性的reference.load方法來手動載入相關資料。

資料模型更改如下:

public

class

score

public

int studentscore //

學生分數

public

int studentid //

學生id

public

int courseid //

課程id

//變成了泛型

public

virtual liststudent //

virtual關鍵字修飾,用於延遲載入 提高效能 只有顯式呼叫時 才會載入 並可以代表乙個student物件 也就是 屬性==物件

public

virtual course course //

virtual關鍵字修飾,用於延遲載入 提高效能 只有顯式呼叫時 才會載入 並可以代表乙個course物件 也就是 屬性==物件

}

**如下:

public

actionresult linqtosql()}}

return

view();

}

如果你知道你立即需要每個實體的相關資料,預先載入通常提供最佳的效能。因為單個查詢傳送到資料庫並一次性獲取資料的效率通常比在每個實體上再發出一次查詢的效率更高。例如,在上面的示例中,假定每個系有十個相關的課程,預先載入會導致只有乙個查詢(join聯合查詢)往返於資料庫。延遲載入和顯式載入兩者都將造成11個查詢和往返。在高延遲的情況下,額外的查詢和往返通常是不利的。

另一方面,在某些情況下使用延遲載入的效率更高。預先載入可能會導致生成sql server不能有效處理的非常複雜的聯接查詢。或者,如果您正在處理的是需要訪問的某個實體的導航屬性,該屬性僅為實體集的乙個子集,延遲載入可能比預先載入效能更好,因為預先載入會將所有的資料全部載入,即使你不需要訪問它們。如果應用程式的效能是極為重要的,你最好測試並在這兩種方法之間選擇一種最佳的。

延遲載入可能會遮蔽一些導致效能問題的**。例如,**沒有指定預先或顯式載入但在處理大量實體並時在每次迭代中都使用了導航屬性的情況下,**的效率可能會很低(因為會有大量的資料庫往返查詢)。乙個在開發環境下表現良好的應用程式可能會在移動到windows azure sql資料庫時由於增加了延遲導致延遲載入的效能下降。你應當分析並測試以確保延遲載入是否是適當的

@陳臥龍的部落格

EF 延遲載入和預先載入

最近悟出來乙個道理,在這兒分享給大家 學歷代表你的過去,能力代表你的現在,學習代表你的將來。十年河東十年河西,莫欺少年窮 學無止境,精益求精 本節 延遲載入和預先載入 entity framework作為乙個優秀的orm框架,它使得運算元據庫就像操作記憶體中的資料一樣,但是這種抽象是有效能代價的,故...

EF延遲載入 懶載入

關於ef懶載入英文翻譯lazyload也俗稱延遲載入 只有是 導航屬性 並且 類是public 字段必須用virtual 才能用延遲載入,ef預設是延遲載入的,什麼是延遲載入呢?延遲載入就是當需要用到集合的時候才會去資料庫取資料,有點是什麼呢?優點就是按需取資料提高了載入的速度,缺點是需要多次執行s...

EF 延遲載入技術

延遲載入 優點 只在需要的時候載入資料,不需要預先計畫,避免了各種複雜的外連線 索引 檢視操作帶來的低效率問題 使用方式 兩步 第一 在需要延遲載入的屬性前加上virtual 該屬性的型別可以是任務的集合型別icolloct或者是0 1.1關聯屬性。如 publicvirtuallistproduc...