轉自 http://www.cnblogs.com/fly_dragon/archive/2011/02/21/1959933.html
IEnumerable接口
公開枚舉器,該枚舉器支持在指定類型的集合上進行簡單迭代。也就是說:實現了此接口的object,就可以直接使用foreach遍歷此object;
IQueryable 接口
它繼承 IEnumerable 接口,而因為.net版本加入Linq和IQueryable后,使得IEnumerable不再那么單調,變得更加強大和豐富。
為了區別兩個接口,我們通過一個實際的例子來解釋一下。
根據上篇隨筆的實例,編寫如下代碼:
static void Main(string[] args)
{
//創建數據庫訪問網關
using (SchoolDBEntities schoolEntities = new SchoolDBEntities())
{
//查詢的結果放入IQueryable接口的集合中
IQueryable<T_Class> classesIQue = (from c in schoolEntities.T_Class
orderby c.ID
select c).Skip<T_Class>(3).Take<T_Class>(3);
//注意這個AsEnumerable<T_Class>()在分頁查詢之前,先將其轉換成IEnumerable類型
IEnumerable<T_Class> classesIEnu = (from c in schoolEntities.T_Class
orderby c.ID
select c).AsEnumerable<T_Class>().Skip<T_Class>(3).Take<T_Class>(3);
//因為啟用了延遲加載機制,所以下面調用一下,才會真正去讀取數據庫
int i = 0;
foreach (var c in classesIQue)
{
i++;
}
Console.WriteLine(i);
foreach (var c in classesIEnu)
{
i++;
}
Console.WriteLine(i);
}
Console.WriteLine("OK");
Console.ReadKey();
}
注意紅色代碼部分,在用linq查詢實體集合之前我先將其轉換成 IEnumerable接口類型,看看最終執行的sql是怎樣的。
第一種:直接返回 IQueryable類型的查詢,如下圖所示:
第二種:在用分頁查詢之前先將其轉換成 IEnumerable實際執行的sql如下圖所示:
總結
IQueryable接口與IEnumberable接口的區別: IEnumerable<T> 泛型類在調用自己的SKip 和 Take 等擴展方法之前數據就已經加載在本地內存里了,而IQueryable<T> 是將Skip ,take 這些方法表達式翻譯成T-SQL語句之后再向SQL服務器發送命令,它並不是把所有數據都加載到內存里來才進行條件過濾。