C# :IQueryable IEnumerable

文章目錄

  • 1. IEnumerable
  • 2. IQueryable
  • 3. LINQ to SQL
  • 4. IEnumerable & IQueryable
    • 4.1 Expression
    • 4.2 Provider

image.png

1. IEnumerable

namespace System.Collections:
public interface IEnumerable
{public IEnumerator GetEnumerator ();
}public interface IEnumerator
{pubilc object Current { get; }public bool MoveNext ();public void Reset ();
}

IEnumerable 只有一個方法 GetEnumerator(), 既實現IEnumerable的所有泛型集合,都具備可枚舉(IEnumerator)的能力

IEnumerator 只有一個屬性 Current,和兩個方法 MoveNext() \ Reset()

通過 MoveNext()Current 可以不停地移動 enumerator 的位置并返回當前的元素。

Reset() 會將 enumerator 設置到初始位置,既第一個元素之前

2. IQueryable

namespace System.Linq:public interface IQueryable<out T> : System.Collections.Generic.IEnumerable<out T>, System.Linq.IQueryable {}public interface IQueryable : System.Collections.IEnumerable
{// 表達式樹返回結果的元素類型public Type ElementType { get; }// 獲取IQueryable實例的表達式樹public System.Linq.Expressions.Expression Expression { get; }public System.Linq.IQueryProvider Provider { get; }
}// 定義用于創建和執行IQueryable對象所描述的查詢的方法
public interface IQueryProvider
{public System.Linq.IQueryable CreateQuery(System.Linq.Expressions.Expression expression);public System.Linq.IQueryable<TElement> CreateQuery<TElement> (System.Linq.Expressions.Expression expression);public object? Execute(System.Linq.Expressions.Expression expression);public TResult Execute<TResult> (System.Linq.Expressions.Expression expression);
}

IQueryable 繼承 IEnumerable,所以 IQueryable 具備可枚舉的能力。

IQueryable 中的 Expession / Provider 則用來實現LINQ to SQL,具體可以看接下來的2節詳細解釋。

3. LINQ to SQL

LINQ to SQL是.Net Framework v3.5的組件,是能夠提供將關系數據作為對象管理的運行時基礎結構。

以往,編程語言通過 API 訪問數據庫數據的時候,需要將查詢語句轉為文本字符串。LINQ to SQL則會將對象模型中的語言集成查詢轉換為SQL,并發給數據庫執行。當返回結果時,LINQ to SQL會再轉換回可以用編程語言處理額對象。

所以,當擁有一個查詢的時候,并不意味著查詢已經執行:

var q = from c in dbContext.Customers Where c.City == ":London" select c;

命令對象會保留描述查詢的字符串,IQueryable 對象的 Expression。命令對象的 ExecuteReader() 方法執行后,以 DataReader 形式返回結果。IQueryable 對象通過 GetEnumerator() 方法返回 IEnumerator 結果。

如下 foreach 會執行兩次 query,這種行為成為延遲執行

var q =from c in db.Customerswhere c.City == "London"select c;
// Execute first time
foreach (Customer c in q)Console.WriteLine(c.CompanyName);
// Execute second time
foreach (Customer c in q)Console.WriteLine(c.CompanyName);

如果提前將結果轉為任意標準的集合類,可以避免重復執行。

var q =from c in db.Customerswhere c.City == "London"select c;
// Execute once using ToList() or ToArray()
var list = q.ToList();
foreach (Customer c in list)Console.WriteLine(c.CompanyName);
foreach (Customer c in list)Console.WriteLine(c.CompanyName);

更多資料:LINQ:.NET Language-Integrated查詢

4. IEnumerable & IQueryable

4.1 Expression

針對 IEnumerable所設計的擴展方法都將表達式視為委托,而針對 IQueryable 的那些擴展方法用的則是表達式樹(expression tree)

IQueryable 會解析表達式樹,并把這棵樹表示的邏輯轉為 provider 能夠操作的格式,將其放在離數據最近的地方去執行。即傳輸數據往往會少于 IEnumerable,總體性能更好。

借鑒 《Effective C#》中的例子,如下兩種寫法,返回的結果相同,但是工作方式卻不同:

// 1. use IQueryable
var q = from c in dbContext.Customers Where c.City == ":London" select c;
var finalAnswer = from c in q ordery c.Name select c;// 2. use Enumerable
var q = (from c in dbContext.Customers where c.City == "London" select c).AsEnumerable();
var finaAnswer = from c in q orderby c.Name select c;

方法1,采用的是 IQueryable內置的 LINQ to SQL,q的查詢語句,會和 第二行的組合起來,即只需要向數據庫發送一次調用,where和orderby會在同一次sql查詢操作里完成

方法2,則是把數據庫對象從 IQueryable 強制轉為了 IEnumerable形式的標準可枚舉對象,即先向數據庫發送查詢請求,獲得所有的數據后,放在本地進行排序操作

假如每種方法第二行還有一次 where 篩選一部分數據,那么方法1會組合2次 where,數據庫只會返回最終目標數據集。而方法2會先從數據把所有第一次 where 得到的數據傳到本地,之后在本地再次篩選,無疑增加了網絡數據傳輸量。

4.2 Provider

IQueryable 的 Provider 未必能支持每一種查詢方式,只能支持某些固定的運算符、方法,所以一旦查詢操作里面調用除此之外的方法,那么就有可能把序列當成 IEnumerable 來查詢,而非 IQueryable,否則會拋出異常。

再上 《Effective c#》例子:

private bool isValidProduct(Product p) => p.ProductName.LastIndexOf('C') == 0;// 1. 轉為 Enumerable 執行
var q1 = from p in dbContext.Products.AsEnumerable() where isValidProduct(p) select p;// 2. 直接執行 IsValidProduct
var q2 = from p in dbContext.Products where isValidProduct(p) select p;

方法1可以正常運行,只是在 AsEnumerable() 之后,查詢必須在本地執行,where 字句內的邏輯由LINQ to Objects處理。

方法2則會拋出異常,因為IQueryProvider會把查詢操作轉為T-SQL,交由遠端執行。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21938.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21938.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21938.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

氣泡式水位計施工技術要求

1、氣泡式水位計壓力氣管出氣口應安裝并固定在最低水位處&#xff0c;其壓力氣管也應固定&#xff0c;有條件的可用金屬管或塑料管保護。氣泡式水位計安裝示意圖見附圖。 2、安裝要求 1&#xff09;檢查氣泡式水位計氣管外觀有無破損及變形&#xff1b; 2&#xff09;旋開帶有…

面試數據庫八股文十問十答第十期

面試數據庫八股文十問十答第十期 作者&#xff1a;程序員小白條&#xff0c;個人博客 相信看了本文后&#xff0c;對你的面試是有一定幫助的&#xff01;關注專欄后就能收到持續更新&#xff01; ?點贊?收藏?不迷路&#xff01;? 1&#xff09;為什么不推薦多表Join&…

特征工程技巧—Bert

前段時間在參加比賽&#xff0c;發現有一些比賽上公開的代碼&#xff0c;其中的數據預處理步驟值得我們參考。 平常我們見到的都是數據預處理&#xff0c;現在我們來講一下特征工程跟數據預處理的區別。 數據預處理是指對原始數據進行清洗、轉換、縮放等操作&#xff0c;以便為…

Blackwell未來發展之路究竟如何?

英偉達Blackwell如何重塑AI計算的未來&#xff1f; 前言 臺灣大學演講 就在6月2日&#xff0c;英偉達CEO黃仁勛在中國臺灣大學綜合體育館發表了最新的演講。這次黃仁勛的演講依舊重磅&#xff0c;更值得注意的是這次演講中還透露了Blackwell今后的發展之路。 介紹Blackwell 介紹…

MongoDB CRUD操作:地理位置查詢

MongoDB CRUD操作&#xff1a;地理位置查詢 文章目錄 MongoDB CRUD操作&#xff1a;地理位置查詢地理空間數據GeoJSON對象傳統坐標對通過數組指定&#xff08;首選&#xff09;通過嵌入文檔指定 地理空間索引2dsphere2d 地理空間查詢地理空間查詢運算符地理空間聚合階段 地理空…

拿筆記下來!產品采購制造類合同怎樣寫比較穩妥?

拿筆記下來&#xff01;產品采購制造類合同怎樣寫比較穩妥&#xff1f; 近日&#xff0c;幾經波折&#xff0c;泰中兩國終于完成了潛艇采購談判&#xff01;你知道嗎&#xff1f;產品制造類合同或協議在起草前如果沒有充分考慮各種因素&#xff0c;可能會導致一系列問題和不利…

C語言學習:數據類型

一、 為什么要引入數據類型 ? 計算機中每個字節都有一個地址&#xff08;類似門牌號&#xff09; ? CPU通過 地址 來訪問這個字節的空間 0x20001103 1 0 0 1 0 0 1 1 0x20001102 1 1 1 0 1 1 1 0 0x20001101 1 1 1 1 0 1 0 1 0x20001100 0 …

linux c socket編程里SO_REUSEADDR的作用

比如下面的代碼 int reuse 1; int ret setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)); if (ret SOCKET_ERROR) {log_error("_SetReuseAddr failed, err_code%d, fd%d", _GetErrorCode(), fd); }代碼解釋 setsockopt 函數用于設置…

無人監控視頻輸出卡頓狀態

設計思路&#xff0c;如下&#xff1a; 1.通過采集卡將視頻信號輸出到個人PC中 2.PC按設置好的時間&#xff0c;視頻屬性分片保存 3.將步驟2中的視頻&#xff0c;按預處理要求&#xff0c;得到待計算的視頻片段 4.使用SSIM算法計算預處理后的視頻&#xff0c;將計算得到的數據存…

聊天機器人的實踐過程

一、語聊機器人 OpenAI 的爆火&#xff0c;到如今也才一年多的時間&#xff0c;然而在過去的一年中&#xff0c;生成式AI的落地場景幾乎 80%都是 ChatBot 的形式&#xff0c;那么今天這篇文章我們就來聊一下&#xff0c;生成式AI和IM能擦出怎么樣的火花&#xff1f;以及各種場…

p13idea的其他操作

1 導入模塊 錯誤示范&#xff1a; 正確示范&#xff1a; 2 刪除模塊 必須用delete才能刪除干凈&#xff0c;用remove刪了之后還要回到文件里面把它刪除掉

有錢還系統源碼 人人還眾籌還錢模式還貸系統源碼

盈利模式&#xff1a; 1.系統里直推400 2.間推得200 3.升級是隔代匹配200 4.漏單直接設置歸系統 5.九級匹配不到直接歸平臺 有錢還平臺新注冊會員&#xff0c;即新入的負債者要分9次分別資助先來的11名負債者每人200元&#xff0c;這筆資助不是一次性給到對方&#xff0c…

Prism 入門04,導航功能

當前章節,沿用 上一章使用Prism 框架創建的WPF 項目空模板。在上一章節,各個不同的模塊之間能夠進行切換并把內容呈現在主程序的頁面當中(其實是通過在主程序中注冊的區域去發起一個導航的請求,然后跳轉到對應的視圖。也就是實現了導航跳轉功能)。 為什么能實現導航的跳轉?…

Mybatis的一級緩存

緩存 MyBatis 包含一個非常強大的查詢緩存特性,它可以非常方便地配置和定制。MyBatis 3 中的緩存實現的很多改進都已經實現了,使得它更加強大而且易于配置。 Mybatis和Hibernate一樣&#xff0c;也有一級和二級緩存&#xff0c;同樣默認開啟的只有一級緩存&#xff0c;二級緩…

docker-compose安裝多環境apollo

下載數據庫sql文件 https://github.com/apolloconfig/apollo/blob/master/scripts/sql/src/apolloconfigdb.sql https://github.com/apolloconfig/apollo/blob/master/scripts/sql/src/apolloportaldb.sql 創建庫并導入表 #生產環境 mysql> CREATE DATABASE IF NOT EXIS…

腦部磁共振成像腫瘤分割方法(MATLAB 2018)

近年腦腫瘤發病率呈上升趨勢&#xff0c;約占全身腫瘤的5%&#xff0c;占兒童腫瘤的70%。CT、MRI等多種影像檢查方法可用于檢測腦腫瘤&#xff0c;其中MRI應用于腦腫瘤成像效果最佳。精準的腦腫瘤分割是病情診斷、手術規劃及后期治療的必備條件&#xff0c;既往研究者對腦部腫瘤…

Python知識點12---Python的I/O操作

提前說一點&#xff1a;如果你是專注于Python開發&#xff0c;那么本系列知識點只是帶你入個門再詳細的開發點就要去看其他資料了&#xff0c;而如果你和作者一樣只是操作其他技術的Python API那就足夠了。 Python的流(I/O)操作&#xff0c;最簡單的其實就是輸入和輸出&#x…

擴展翡蜀定理問題

問題描述 給定一個大小為 n n n 的集合 A { a 1 , a 2 ~ a n } A\{a_1,a_2 \sim a_n\} A{a1?,a2?~an?}&#xff0c;滿足條件 gcd ( A ) 1 \text{gcd}(A)1 gcd(A)1。 O ( 1 ) O(1) O(1)時間內 求最大的 k k k &#xff0c;滿足不存在一個大小為 n n n 的非負數集合…

工廠的精益生產如此重要

什么是工廠的精益生產 精益生產&#xff08;Lean Manufacturing&#xff09;是一種起源于20世紀50年代日本豐田汽車公司的生產管理哲學。它的核心理念是通過消除生產過程中的浪費&#xff0c;優化流程&#xff0c;提高效率&#xff0c;從而實現成本降低和質量提升。精益生產不僅…

VRTK4.0學習——(二)

手柄綁定以及顯示 1.導入CameraRigs.UnityXRPluginFramework 和 CameraRigs.TrackedAlias 預設&#xff0c;將CameraRigs.UnityXRPluginFramework拖入CameraRigs.TrackedAlias的Elements中即可&#xff0c;運行軟件后即可看到手柄了 注&#xff1a;如果無法看到手柄&#xff…