我們做項目時,難免會遇到用的不知道是啥,及把linq和EF搞混了
今天我帶領大家梳理下思路:
首先說linq查詢,然后介紹EF查詢
1.linq查詢
當我們使用linq查詢時,轉到定義會調到Queryable 類, 那么也就是說,這個類封裝了linq所有查詢的方法,那么我們來研究研究這個類
MSDN上是這樣解釋的:提供一組用於查詢實現 IQueryable<T> 的數據結構的 static(在 Visual Basic 中為 Shared)方法。
命名空間: System.Linq
程序集: System.Core(System.Core.dll 中)
通過截圖可以看出是提供了“IQueryable<T> 的數據結構的 static方法"。
那么有的人可能並不知道IQueryalbe是干啥的,那么我來解釋下:
IQueryable和IList一樣,是用於接收一組數據的集合,
那么IQueryable和IList有有何區別,看下面
-------------------------------------------------------------------------------------
1.IQeurable(IQuerable<T>)不會立即在內存里創建持久數據,只有遍歷它(如通過foreach)、把它轉換成List等情況下才會向內存加載數據,它可以實現“延期執行”,如果當前被加載的實體有關聯實體(associations),此關聯實體可被接下來的訪問加載。
2.IList(IList<T>)會立即在內存里創建持久數據,這就沒有實現“延期執行(deferred execution)”,如果被加載的實體有關聯實體(associations),此關聯實體不會被加載(既不立即加載,也不延遲加載)。
看下面一段代碼:
//IList的情況
IList users = res.ToList(); //此時已把users加載到內存,而每個user的關聯實體(UserInfos)未被加載,所以下一行代碼無法順利通過var ss = users.Where(p => p.UserInfos.ID != 3); //此處報錯,因為P的UserInfos實體無法被加載
這提醒了我們有關聯實體時,不要使用ToList();
// IQuerable的情況
IQueryable users = res.AsQueryable(); //users未被立即加載,關聯實體可通過“延遲加載”獲得var ss = users.Where(p => p.UserInfos.ID != 3);//此處順利獲得對應的ss
---------------------------------------------------------------------------------------------------
上面提到了IList和IQueryalbe,那么再把這兩個方法擴展下,弄清到底是什么東東?
-------------------------------------------------------------------------------------
首先看Ilist介紹:
繼承順序如下:
Ilist->ICollection ->IEnumerable
->Ilist
為了方便理解,我把知道的都Copy過來好了
首先IList 泛型接口是 ICollection 泛型接口的子代,並且是所有泛型列表的基接口。
它僅僅是所有泛型類型的接口,並沒有太多方法可以方便實用,如果僅僅是作為集合數據的承載體,確實,IList<T>可以勝任。
不過,更多的時候,我們要對集合數據進行處理,從中篩選數據或者排序。這個時候IList<T>就愛莫能助了。
1、當你只想使用接口的方法時,ILis<>這種方式比較好.他不獲取實現這個接口的類的其他方法和字段,有效的節省空間.
2、IList <>是個接口,定義了一些操作方法這些方法要你自己去實現
List <>是泛型類,它已經實現了IList <>定義的那些方法
IList <Class1> IList11 =new List <Class1>();
List <Class1> List11 =new List <Class1>();
這兩行代碼,從操作上來看,實際上都是創建了一個List<Class1>對象的實例,也就是說,他們的操作沒有區別。
只是用於保存這個操作的返回值變量類型不一樣而已。
那么,我們可以這么理解,這兩行代碼的目的不一樣。
List <Class1> List11 =new List <Class1>();
是想創建一個List<Class1>,而且需要使用到List<T>的功能,進行相關操作。
而
IList <Class1> IList11 =new List <Class1>();
只是想創建一個基於接口IList<Class1>的對象的實例,只是這個接口是由List<T>實現的。所以它只是希望使用到IList<T>接口規定的功能而已。
->Ilist->ICollection->IEnumerable
ICollection就不介紹了,直接介紹最基礎的IEnumerable
IEnumerable它允許開發人員定義foreach語句功能的實現並支持非泛型方法的簡單的迭代
IList介紹完畢,接着看IQueryalbe
轉到定義可以看到和IList一樣,繼承自IEnumerable<T>
-------------------------------------------------------------------------------------
Queryable類提供的基本查詢方法:Where,Select,,,
舉例:user.Select(u=>u.id).AsQueryable(); db.User.Where().ToList();
linq查詢介紹完畢!
2.EF查詢
轉到定義可以看到,所有EF查詢方法都繼承自DbSet類,那么我們就以這個類說起:
簡要截圖:
這個類提供了我們最常用的方法 :Add(TEntity entity),Remove(TEntity entity),Find(params object[] keyValues)
EF查詢介紹完畢!
End:看了上面的介紹,有些人會糾結linq中的select,where和find用法怎么覺得用哪個也行,接下來我來區分下:
select提供方法如下:
public static IQueryable<TResult> Select<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector);
where提供的方法如下:
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, int, bool>> predicate);
find提供的方法如下:
public virtual TEntity Find(params object[] keyValues);
根據我實際測試得知:如果有主外鍵表相關操作時,用EF的find方法,其余能通用的都能通過,
另外注意上面的返回值類型,linq兩個方法返回的都是集合,find返回的是單個實體。但有一點是,它們都可以用var來接收