<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          IQueryable 和 IEnumerable 的區(qū)別

          共 1912字,需瀏覽 4分鐘

           ·

          2022-07-13 19:12

          推薦關(guān)注「碼俠江湖」星標(biāo),時刻不忘江湖事

          這是 EF Core 系列的最后一篇文章,按照上一篇的計劃,我們最后就講一講 IQueryable 和 IEnumerable 的區(qū)別。

          點擊上方或后方藍字,閱讀 EF Core 系列合集

          在前面的一些例子中,我們會在使用 LINQ 查詢方法之后,又使用 ToList 等方法,將查詢結(jié)果轉(zhuǎn)換成集合。

          如果我們不使用 ToList 呢?

          比如這個示例:

          using var context = new BloggingContext();
          var posts = context.Posts.OrderBy(p => p.BlogId == 1).ToList();
          var posts1 = context.Posts.OrderBy(p => p.BlogId == 1);

          這里有兩個查詢,一個使用了 ToList 方法,另一個沒有。

          執(zhí)行這段代碼,在控制臺中查看日志:

          可以看到只有一條 SQL 語句被執(zhí)行,按理說我們有兩個 LINQ 查詢,應(yīng)該有兩條 SQL 語句,但是只有一條,這是為什么?

          其實,我們調(diào)用的 LINQ 查詢方法,本身是不會執(zhí)行查詢操作的。

          簡單來說,我們執(zhí)行的 LINQ 方法,只是轉(zhuǎn)換成了查詢表達式,被存儲在了 IQueryable 類型的對象中。

          只有當(dāng)我們需要數(shù)據(jù)的時候,比如當(dāng)我們使用 ToList 方法時,EF Core 才會將整個出啊訊表達式,翻譯成 SQL 語句執(zhí)行。

          這種需要數(shù)據(jù)時才會查詢的行為,看起來有點像顯式加載,但絕對不是一回事兒。

          結(jié)合示例簡單的說,「post1」 只是一個以 LINQ 表達式體現(xiàn)的查詢語句,就好比你編寫了一條字符串 SQL 語句。

          至于這條語句是否執(zhí)行,取決于下一步操作。比如 ToList 方法,就是這一步查詢操作。

          因為使用 ToList 方法的目的,就是為了獲取數(shù)據(jù)集合,所以 EF Core 才會執(zhí)行這條查詢語句。

          如果非要給這種行為起一個名字的話,我覺得應(yīng)該叫延遲執(zhí)行更合適。

          我們再來看看,LINQ 方法返回的數(shù)據(jù)類型是什么:

          「post1」 的數(shù)據(jù)類型是泛型的 IOrderedQueryable,它本質(zhì)上是就是一個 IQueryable 類型,不過是具有排序表達式的 IQueryable。

          LINQ 方法往往都有好幾個重載,比如 OrdeyBy、Where 等方法,它們返回的數(shù)據(jù)類型有兩種:IQueryableIEnumerable。

          那么這兩種數(shù)據(jù)類型究竟有何區(qū)別?我們做個試驗:

          在這個示例中,「posts」「posts1」 的語句,可以視為等效的。

          這是因為查詢參數(shù)會被默認為 IQueryable 類型,所以最終使用的還是返回 IQueryable 類型的重載方法。

          在 post2 的語句中,由于 IQueryable 繼承了 IEnumerable,所以可以通過 AsEnumerable 方法,將其返回值轉(zhuǎn)換為 IEnumerable 類型。

          在這種情況下,只有當(dāng)代碼運行到兩個 foreach 遍歷的時候,才會真正的執(zhí)行語句。

          接下來,再看這個示例:

          這個示例與前面一個示例的不同之處在于,「posts1」 查詢語句的 LINQ 方法在 AsEnumerable 之后才調(diào)用。

          運行程序,觀察控制臺日志:

          此時我們終于發(fā)現(xiàn)了不同,兩條 SQL 語句不同,第一條 SQL 語句比第二條 SQL 語句多了一個分頁操作。

          IQueryable 在查詢的時候,會應(yīng)用所有 LINQ 方法,并且生成一個完整的 SQL 查詢語句,去數(shù)據(jù)庫執(zhí)行并獲取符合查詢語句的數(shù)據(jù);

          而當(dāng)我們使用 IEnumerable 時,則會生成一條將所有的數(shù)據(jù)查詢出來的 SQL 語句,而后在內(nèi)存中再對數(shù)據(jù)進行處理,最終獲得符合查詢語句的數(shù)據(jù)。

          在不使用 AsEnumerable 的情況下,默認都是采用 IQueryable 進行查詢。

          那么我們什么時候應(yīng)該使用 AsEnumerable ?

          使用 「AsEnumerable」 的查詢,稱為客戶端查詢。

          比如,當(dāng)你想在客戶端完成篩選或者聚合等操作的時候,可以選擇轉(zhuǎn)換成 IEnumerable 進行查詢。

          雖然這增大了數(shù)據(jù)庫查詢壓力和IO壓力,但因為將計算轉(zhuǎn)移到了客戶端,所以也相應(yīng)的減輕了數(shù)據(jù)庫的計算壓力。

          簡單來說是,這是一種用 I/O 資源換計算資源的行為。


          瀏覽 44
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品一二 | 亚洲1区2区3区4区5区 | 超碰中文在线 | 青娱乐极品视觉盛宴国产视频 | 激情中文字幕在线观看 |