第五節: EF高級屬性(一) 之 本地緩存、立即加載、延遲加載(不含導航屬性)


一. 本地緩存

   從這個章節開始,介紹一下EF的一些高級特性,這里介紹的首先介紹的EF的本地緩存,在前面的“EF增刪改”章節中介紹過該特性(SaveChanges一次性會作用於本地緩存中所有的狀態的變化),在這里介紹一下本地緩存的另外一個用途。

  ① Find方法通過主鍵查詢數據,主鍵相同的查詢,只有第一次訪問數據庫,其它均從緩存中讀取。

  ② 延遲加載的數據,在第一次使用的使用時訪問數據庫,后面無論再使用多少次,均是從內存中讀取了。

1             Console.WriteLine("--------------------------- 1.本地緩存屬性   ------------------------------------");
2                 db.Database.Log += c => Console.WriteLine(c);
3                 //以下4個根據主鍵id查詢,查詢了一次,都存到本地緩存里了,所以user2不查詢數據庫,但user3的id不同,所以查詢數據庫
4                 var user1 = db.Set<TestInfor>().Find("2");
5                 var user2 = db.Set<TestInfor>().Find("2");
6                 var user3 = db.Set<TestInfor>().Find("3");

二. 立即加載

  這里的立即加載指單表,不含主外鍵的情況。

  所謂的立即加載就是代碼執行的時候直接去數據庫查詢,與是否立即使用無關,查出來后放到本地緩存里,以后再次使用的時候,從本地緩存中讀取。

  常見的立即加載的的標記:toList() 、FirstOrDefault() 。

1         Console.WriteLine("--------------------------- 2.即時加載   ------------------------------------");
2 
3                 ////以下3個屬於立即查詢,所以每次都要查詢數據庫,不緩存
4                 var user5 = db.Set<TestInfor>().Where(u => u.id == "2").FirstOrDefault();
5                 var user6 = db.Set<TestInfor>().Where(u => u.id == "2").FirstOrDefault();
6                 var user7 = db.Set<TestInfor>().Where(u => u.id == "2").FirstOrDefault();

三. 延遲加載

這里的延遲加載指單表,不含主外鍵的情況。

1. 定義:只有我們需要數據的時候,才去數據庫查詢

  比如:我們需要根據條件判斷,通過Where來拼接條件(IQueryable),在拼接的過程中,並沒有訪問數據庫,只有在最終使用的時候,才訪問數據庫。

  特別注意:調用的時候要foreach循環來調用,只有第一次使用的時候去訪問數據庫,其它的都是從本地緩存中讀取。

2. 禁用延遲加載的方法:

a:如果結果是集合,在拼接的結尾加 toList() ,其它類型調用其它方法

b:如果結果是單個實體,在拼接的結尾加 FirstOrDefault()

3. 好處:保證了數據的實時性,什么時候用,什么時候查詢

4. 弊端:每用一次,就需要查詢一次數據,服務器壓力大

5. 延遲加載的實際開發場景:

分頁要要經歷where多個條件查詢、skip、take、toList,如果每調用一個方法都連接一個數據庫,那么在拼接過程中就訪問了3次數據庫,而且可能數據量非常多,所以這個時候使用延遲加載,只有在所有sql語句拼接完的最后一步才連接數據庫。

總結:只要查詢結果實現了IQueryable接口類的,那么查詢結果都是延遲加載的。

 1           Console.WriteLine("--------------------------- 3.延遲加載   ------------------------------------");
 2                 IQueryable<TestInfor> user4 = db.Set<TestInfor>().Where(u => u.id != "123");
 3                 IQueryable<TestInfor> user6 = db.Set<TestInfor>().Where(u => u.id != "123");
 4                 foreach (var item in user4)
 5                 {
 6                     Console.WriteLine("我要從數據庫中讀取數據了:" + item.txt1);
 7                 }
 8                 foreach (var item in user4)
 9                 {
10                     Console.WriteLine("我要從數據庫中讀取數據了2:" + item.txt1);
11                 }
12                 foreach (var item in user6)
13                 {
14                     Console.WriteLine("我要從數據庫中讀取數據了3:" + item.txt1);
15                 }

延遲加載上述案例分析:

* IQueryable類型的 user4和user6, 都是延遲加載的,下面foreach第一次使用該對象的時候去數據庫查詢。

* 這里會有這么幾個問題:

* ①:foreach第一次遍歷的時候去數據庫中查詢user4,然后放到本地緩存里,后面無論循環多少次,都是從本地緩存中讀取user4。

* ②:前兩個foreach操控的對象都是user4,所以第二個foreach無論哪次循環,都是從本地緩存中讀取

* ③:第三個foreach操控的對象是user6,同樣是在foreach第一次循環的時候去數據庫查詢,所以在代碼執行到第一個或第二個foreach的時候,

* 手動去數據庫改數據,當執行到第三個foreach,查詢出來的數據就是修改后的了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM