首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

LINQ 學習筆記:OrderBy/ThenBy 排序操作完整指南 (多鍵排序、倒序、比較器、IOrderedEnumerable)

     編輯:關於SqlServer

LINQ 排序運算子提供強大的多層級排序能力,對應 SQL ORDER BY。本文系統整理 OrderBy/ThenBy、倒序版本、Reverse、自訂比較器與 IOrderedEnumerable 型別系統的實務陷阱。

核心排序運算子

方法SQL 對應輸入型別輸出型別
OrderByORDER BY key ASCIEnumerable<T>IOrderedEnumerable<T>
OrderByDescendingORDER BY key DESCIEnumerable<T>IOrderedEnumerable<T>
ThenBy, key ASCIOrderedEnumerable<T>IOrderedEnumerable<T>
ThenByDescending, key DESCIOrderedEnumerable<T>IOrderedEnumerable<T>
Reverse無對應IEnumerable<T>IEnumerable<T>

基礎與多鍵排序


string[] names = { "James", "Jack", "Todd", "David", "Kobe" };

// 單鍵:按長度升冪
var q1 = names.OrderBy(n => n.Length); 
// 結果: Jack(4), Todd(4), Kobe(4), James(5), David(5) - 同長度順序不確定

// 多鍵:長度升冪,同長度再按字母升冪
var q2 = names.OrderBy(n => n.Length).ThenBy(n => n);
// 結果: Jack, Kobe, Todd, David, James

// 串聯多個 ThenBy:長度 → 第2字元 → 第1字元
var q3 = names.OrderBy(n => n.Length)
              .ThenBy(n => n[1])
              .ThenBy(n => n[0]);

// 查詢運算式語法 (等效)
var q4 = from n in names
         orderby n.Length, n[1], n[0]
         select n;

倒序排序


// 價格降冊,同價格再按描述升冊
var q = ctx.Purchases
           .OrderByDescending(p => p.Price)
           .ThenBy(p => p.Description);

// 查詢運算式
var q2 = from p in ctx.Purchases
         orderby p.Price descending, p.Description
         select p;

自訂比較器

僅限 **LINQ to Objects (本地查詢)**。LINQ to SQL 不支援,排序邏輯由資料庫 Collation 決定。


// 大小寫無關排序
var q = names.OrderBy(n => n, StringComparer.CurrentCultureIgnoreCase);

// 查詢運算式不支援傳入 comparer,LINQ to SQL 同理
// 解決方案:在 keySelector 內正規化
var qSql = from p in ctx.Purchases
           orderby p.Description.ToUpper()
           select p;

IOrderedEnumerable 型別系統與實務陷阱

OrderBy 回傳 IOrderedEnumerable<T> (或 IOrderedQueryable<T>),此介面**專門允許後續串接 ThenBy** 編譯期檢查。

陷阱 1:隱式型別 var 掩蓋型別錯誤


IOrderedEnumerable q1 = names.OrderBy(n => n.Length); // 明確型別
IOrderedEnumerable q2 = q1.ThenBy(n => n); // ✓ 編譯通過

// 若用 IEnumerable 接收 q1
IEnumerable q1bad = names.OrderBy(n => n.Length);
var q2bad = q1bad.ThenBy(n => n); // ✗ 編譯錯誤:IEnumerable 無 ThenBy

陷阱 2:Where 破壞 IOrderedEnumerable 鏈


var q = names.OrderBy(n => n.Length); // q 是 IOrderedEnumerable
q = q.Where(n => n.Length > 3); // ✗ 編譯錯誤:Where 回傳 IEnumerable,無法指派回 var (IOrderedEnumerable)

// 解決:OrderBy 後立即呼叫 AsEnumerable() 降級
var qFixed = names.OrderBy(n => n.Length).AsEnumerable(); // 現在是 IEnumerable
qFixed = qFixed.Where(n => n.Length > 3); // ✓

// LINQ to SQL 同理:AsQueryable()
var qSql = ctx.Purchases.OrderBy(p => p.Price).AsQueryable();
qSql = qSql.Where(p => p.Price > 100);

Reverse:簡單反轉


var reversed = names.Reverse(); // 完全反轉順序,非排序
// 無 SQL 對應,僅本地集合適用

總結:排序最佳實踐

  • 多鍵排序**優先使用查詢運算式語法** (orderby a, b, c),可讀性最高、型別安全。
  • Lambda 鏈式調用時,**明確型別宣告** 或理解 IOrderedEnumerable 傳遞規則。
  • 需在排序後接 Where/Select 等非排序運算子 → 緊接 AsEnumerable()/AsQueryable() 降級。
  • 資料庫排序大小寫敏感度由 Collation 決定,應用層勿嘗試覆蓋 (改用 ToUpper() 正規化鍵)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved