2026-01-14

[C#] 還在手寫 .Select 轉換 ? 改用 Expression 讓你的 LINQ 查詢高效又好維護

聊一下關於好用的 LINQ 很多時候我們從資料庫撈出資料來,並且透過 API 往外吐,這是後我們都會把肥大的資料

拿掉一些或是組合一些欄位,之後再往外面吐,當然這沒什麼問題但...


我們通常的作法

1. 寫一個轉換 function ,原本的 Order 訂單轉成另一個物件再輸出 OrderOutputModel

public static OrderOutputModel ToOutput(Order o) { return new OrderOutputModel { Id = o.Id, CustomerName = o.Customer.Name, City = o.Customer.Address.City, TotalAmount = o.Lines.Sum(l => l.Price * l.Quantity), CreatedAt = o.CreatedAt }; }

使用的時候

var result = orders .Where(o => o.Id < 10) .Select(o => ToOutput(o)) .ToList();


2. 透過 .Select 進行轉換

var result = orders .Where(o => o.Id < 10) .Select(o => new OrderOutputModel { Id = o.Id, CustomerName = o.Customer.Name, City = o.Customer.Address.City, TotalAmount = o.Lines.Sum(l => l.Price * l.Quantity), CreatedAt = o.CreatedAt }) .ToList();


3. 其實建議解法就是使用 Expression 這樣就可以共用

後期我幾乎都是改這樣作

public static class OrderProjections { public static Expression<Func<Order, OrderOutputModel>> ToOutput => o => new OrderOutputModel { Id = o.Id, CustomerName = o.Customer.Name, City = o.Customer.Address.City, TotalAmount = o.Lines.Sum(l => l.Price * l.Quantity), CreatedAt = o.CreatedAt }; }

使用方法 :

var result = orders .Where(o => o.Id < 10) .Select(OrderProjections.ToOutput) .ToList();

來作個結論,其實以前最開始寫程式,通常我都會用第一個,但是之後再 LINQ 的時代常常因為 "順手"  或是 "方便" 就採用 LINQ 直接 Select 一個新物件出去,但是他的可用性很低

現在基本上如果沒意外通常現在都會使用 Expression 去取代 .Select ,可以集中管理,也可以跟 LINQ 配合

而且在整個專案維護上面也會比較容易。



--

The bug existed in all possible states. Until I ran the code.

如果這篇文章有幫助到您幫我分享一下,讓我有寫下去的動力...