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

  • 481
  • 0

聊一下關於好用的 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 配合

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

--

本文原文首發於個人部落格:[C#] 還在手寫 .Select 轉換 ? 改用 Expression 讓你的 LINQ 查詢高效又好維護

--

---

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