Linq中的Enumerable和Queryable

前言

此文章延續自C#中Linq的使用

正文

上節講到Linq可以通過查詢方法來使用,Linq中有兩個命名空間,分別是System.Linq.EnumerableSystem.Linq.Queryable,兩個命名空間中幾乎擁有相同的方法,使用方式也大致相同,如下:

       int[] y = { 0, 9, 2, 3, 5 };
       Model1Container db = new Model1Container();
       // 使用Enumerable下的方法
       var x2 = x.Where(u => u > 0);
       // 使用Queryable下的方法
       var userSet = db.UserSet.Where(u => u.Id > 0);

使用方式相同吧,但是兩個Where來自不同的命名空間:
這裏寫圖片描述
這裏寫圖片描述

接下來分析它們的不同點

使用場合不同

Enumerable適合在內存數據集合中使用(如數組、List等),Queryable適合在離線數據集合中使用(如EF中的dbContext中的DbSet中使用)
這你不需要自己區分,因爲當數組等內存集合使用linq查詢時自動使用System.Linq.Enumerable下的方法,當EF的dbContext的DbSet使用linq查詢時自動使用System.Linq.Queryable下的方法,至於爲什麼呢?下面的不同點給出答案。

返回類型不同

上面說了VS會根據你使用的數據集合的類型來自動使用相應命名空間下的方法,這是因爲VS選擇了最優的使用。當返回數據集合如Where方法時,Enumerable的Where返回的IEnumerable<>,Queryable的Where返回的是IQueryable<>,這兩個集合有什麼區別呢?IEnumerable<>是本地集合存在內存中,而IQueryable<>屬於離線集合,在使用到返回的集合IQueryable<>才加載數據,屬於延遲加載

  Model1Container db = new Model1Container();
  IQueryable<User> userSet = db.UserSet.Where(u => u.Id > 0);

上面的 db.UserSet使用了Queryable下的Where方法,這個方法需要操作數據庫,但是不立刻操作數據庫,而是等用到userSet時才從數據庫取出數據,屬於延遲加載,提高了效率。

傳遞參數不同

還是這一段代碼:

       int[] y = { 0, 9, 2, 3, 5 };
       Model1Container db = new Model1Container();
       // 使用Enumerable下的方法
       var x2 = x.Where(u => u > 0);
       // 使用Queryable下的方法
       var userSet = db.UserSet.Where(u => u.Id > 0);

當我們封裝一些方法時需要傳遞參數,如上面的代碼,我們想要將

u => u.Id > 0

用參數代替。
別看都是u => u.Id > 0,但是是兩個不同的類型,一個是Func,一個是 Expression,如下:

  Expression<Func<User, bool>> expression = u => u.Id > 0;
  Func<int, bool> expression2 = u => u> 0;

  IEnumerable<int> x2 = x.Where(expression2);
  IQueryable<User> userSet = db.UserSet.Where(expression);

Func和Expression將單獨講解,這裏只需要知道,可以將 lambda 表達式 分配到Func<> 委託中當作參數傳遞;而Expression<>是將Func<>表示成數據結構。
對Func有興趣的可以看下C#中的Func<>

總結

  • Enumerable在本地集合中使用,直接加載到內存中,Queryable在操作數據庫時延遲加載。
  • Enumerable需要的參數是委託類型Func<>,Queryable需要的參數類型是數據結構。
發佈了51 篇原創文章 · 獲贊 30 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章