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

LINQ Select 子句完全攻略:投影、匿名型別、索引、多來源聯結

     編輯:關於.NET

select 子句是 LINQ 查詢的「輸出塑形器」,決定查詢結果的結構與內容。本文透過四大實戰範例,系統化展示 select 的核心用法與進階技巧。

1. 資料轉換與格式化

對查詢結果逐元素套用轉換邏輯:


string[] names = { "Jack", "Bob", "Bill", "Catty", "Willam" };

var rs = from n in names
         where n.StartsWith("B")
         select n.ToLower(); // 投影:轉小寫

foreach (var r in rs) Console.WriteLine(r);
// 輸出: bob, bill
💡 select 後的運算式可為任意 C# 運算式:方法呼叫、運算子、三元運算子、物件初始化器等。

2. 匿名型別投影 (投影所需欄位)

LINQ to SQL 查詢資料庫時,僅選取必要欄位可大幅降低網路傳輸與記憶體佔用:


var ctx = new NorthwindDataContext();

var cs = from c in ctx.Customers
         where c.ContactName.StartsWith("B")
         select new
         {
             CustomerID = c.CustomerID,
             CustomerName = c.ContactTitle + " " + c.ContactName
         };

foreach (var c in cs) Console.WriteLine(c);
// 輸出: { CustomerID = BERGS, CustomerName = Order Administrator Beate Vileid } ...
  • 編譯器自動產生唯讀匿名型別,屬性名稱若省略則推斷自運算式 (如 c.CustomerID → CustomerID)。
  • 匿名型別僅限方法內部使用,跨方法傳遞需定義具名 DTO/Record 型別 (C# 9+ record 最適合)。

3. 索引感知投影 (僅限方法語法)

陣列/List<T> 等索引集合,可在 Select 取得元素索引:


string[] names = { "Jack", "Bob", "Bill", "Catty", "Willam" };

var rs = names.Select((name, index) => new { Name = name, Index = index });

foreach (var r in rs) Console.WriteLine($"{r.Index}: {r.Name}");
// 輸出:
// 0: Jack
// 1: Bob
// 2: Bill
// 3: Catty
// 4: Willam
⚠️ 查詢語法 from ... select **不支援** 索引參數,必須使用方法語法 Select((x,i) => ...)。

4. 多來源聯結查詢 (SelectMany / 多 from 子句)

相當於雙重迴圈或 SQL CROSS JOIN / INNER JOIN:

記憶體集合:交叉篩選


int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
int[] numbersB = { 1, 3, 5, 7, 8 };

var pairs = from a in numbersA
            from b in numbersB
            where a < b
            select new { a, b };

foreach (var p in pairs) Console.WriteLine($"{p.a} < {p.b}");
// 等同 numbersA.SelectMany(a => numbersB.Where(b => a < b).Select(b => new {a,b}))

LINQ to SQL:導航屬性聯結 (子查詢語意)


var ctx = new NorthwindDataContext();

var rs = from c in ctx.Customers
         from o in c.Orders          // 導航屬性 Orders 對應 FK 關聯
         where o.ShipCity.StartsWith("B")
         select new { CustomerName = c.ContactName, OrderID = o.OrderID };

foreach (var r in rs) Console.WriteLine(r);
// 產生 SQL 含 INNER JOIN,非記憶體端 Cross Join

Select 進階模式速查表

模式語法範例適用場景
單值投影select x.Name只需單一欄位/屬性
匿名型別select new { x.Id, x.Name }DTO 形狀、減少載入欄位
具名型別select new CustomerDto { Id=x.Id, Name=x.Name }跨層傳遞、序列化
索引投影.Select((x,i) => new {x, i})需要知道元素位置
扁平化from a in A from b in a.Bs select b一對多展開 (SelectMany)
條件投影select x.Active ? x.Name : "N/A"依條件輸出不同值
巢狀投影select new { x.Name, Children = x.Children.Select(c => c.Name) }階層式 DTO

效能與最佳實務提醒

  1. 避免在 Select 中執行昂貴運算:複雜計算、外部 API 呼叫應在記憶體端 (AsEnumerable() 後) 執行,避免轉譯為 SQL 失敗或效能差。
  2. LINQ to SQL 僅支援參數化運算式:select new { FullName = c.FirstName + " " + c.LastName } 可轉譯;select new { FullName = FormatName(c.FirstName, c.LastName) } (自訂方法) 會拋出例外。
  3. 投影即截斷追蹤:select new { ... } 回傳匿名型別/DTO,**非實體型別**,DataContext 不會追蹤變更,SubmitChanges() 不會持久化。

總結

select 是 LINQ 查詢的「出口」,掌握匿名型別投影、索引感知、多來源扁平化三大核心模式,即可靈活應對從簡單格式化到複雜關聯查詢的各種輸出需求。記住:**查詢語法適合單來源投影,方法語法解鎖索引與 SelectMany 進階能力**。

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