首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

從查詢表達式入門 LINQ:延遲執行、投影、排序、聯接、分組與延續

     編輯:關於.NET

前言

LINQ (Language Integrated Query) 為 C# 提供統一的資料查詢語法,支援記憶體集合、資料庫、XML 等多種資料源。本文從查詢表達式語法切入,詳細解析 from/where/select/orderby/join/group/let/into 等子句的編譯轉換、延遲執行機制與進階用法。

一、查詢表達式基礎結構

var articles = from article in db.Articles
               where article.Name == "JIM"
               select article;
  • 資料源:from article in db.Articles 宣告範圍變數 article 遍歷 db.Articles
  • 篩選:where 子句對應 Where(article => article.Name == "JIM")
  • 投影:select article 對應 Select(article => article) (退化查詢)
  • 延遲執行:查詢建立時不執行,僅生成委托/表達式樹;首次枚舉結果 (如 foreach/ToList()) 才開始逐筆處理

二、核心子句深度解析

1. where - 可多個、邏輯 AND

from a in db.Articles where a.Name=="JIM" where a.Age>20 select a;
// 編譯為 db.Articles.Where(a=>a.Name=="JIM").Where(a=>a.Age>20)

2. select - 投影與匿名型別

select new { Name = article.Name, Upper = article.Name.ToUpper() };
// 建立新物件,隔離來源資料,避免副作用

3. 範圍變數隱式/顯式型別

from article in db.Articles select article; // 隱式,編譯器推斷
from Article article in db.Articles select article; // 顯式,需 Cast<Article>()

顯式型別用於非泛型集合 (如 ArrayList) 或需強制轉型時。

4. orderby - 多鍵排序

from a in db.Articles orderby a.Age descending, a.Height select a;
// 編譯為 OrderByDescending(a=>a.Age).ThenBy(a=>a.Height)
  • OrderBy 回傳 IOrderedEnumerable<T>,支援 ThenBy/ThenByDescending 鏈式
  • 建議單一 orderby 子句包含所有排序鍵

5. let - 引入中間變數 (透明識別碼)

from a in db.Articles
let len = a.Name.Length
orderby len
select new { Name = a.Name, Length = len };

編譯器透過匿名型別包裝原範圍變數與新變數 (透明識別碼) 實現後續子句存取 len。

6. join - 內聯接 / 分組聯接 / 交叉聯接

  • 內聯接:join c in db.Comments on a.Name equals c.ArticleName select new { a.Name, c.Content } 右側序列緩衝,左側流式處理,小表放右側。
  • 分組聯接:join c in db.Comments on a.Name equals c.ArticleName into comments select new { Article=a, Comments=comments } 保留左側所有項目,無對應則為空序列。
  • 交叉聯接:from a in db.Articles from c in db.Comments select new { a, c } 笛卡兒積,無 on 條件。

7. group ... by - 分組

from a in db.Articles where a.Name=="JIM" group a by a.Age;
// 編譯為 Where(...).GroupBy(a=>a.Age, a=>a.Author) 可指定結果選擇器

8. into - 查詢延續

將前一階段查詢結果作為新範圍變數繼續查詢:

from a in db.Articles where a.Name=="JIM"
group a by a.Age into g
select new { Age = g.Key, Count = g.Count() }
into result
orderby result.Count
select result;

可多層延續,但過度使用降低可讀性,建議拆分為多個查詢變數。

三、常用立即執行運算子

方法行為異常處理
First()第一個元素空序列拋出
FirstOrDefault()第一個或 default不拋出
Single()唯一元素零或多個拋出
SingleOrDefault()唯一或 default不拋出
ToList()物質化為 List-
Include("Navigation")EF 急載入導航屬性-

四、IQueryable<T> vs IEnumerable<T>

  • 查詢表達式對 IQueryable<T> (如 EF) 生成 Expression<Func> 表達式樹,由 Provider 轉譯為 SQL
  • 對 IEnumerable<T> 生成 Func<T, bool> 委托,在記憶體中執行
  • 編譯器依賴「鴨子類型」:只檢查方法名稱與參數,不綁定具體型別,允許自訂 LINQ Provider

總結

查詢表達式提供聲明式、類 SQL 的查詢體驗,編譯器將其轉換為標準查詢運算子鏈。理解 延遲執行、透明識別碼 (let/join/group into)、聯接類型 與 查詢延續 是駕馭 LINQ 的關鍵。複雜查詢建議拆分為多個變數或改用方法語法 (Where/Select...) 以提升可讀性與除錯便利性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved