簡體   English   中英

重構LINQ IQueryable表達式以刪除重復的查詢部分

[英]refactoring LINQ IQueryable expression to remove duplicated portions of queries

我有一些具有冗余的linq查詢,我想分解出一段代碼。 這些是IQueryable的連接表達式,重要的是我不會導致查詢比沒有重構時更早地進行評估。

這是一個簡化的查詢:

var result = 
from T in db.Transactions
join O in db.Orders on T.OrderID equals O.OrderID
join OD in db.OrderDetails on O.OrderID equals OD.OrderID into OrderDetails
let FirstProductBought = OrderDetails.First().Select(OD => OD.Product.ProductName)
select new
{
  TransactionID = T.TransactionID,
  OrderID = O.OrderID,
  FirstProductBought = FirstProductBought
};

我想要分解的是“給定訂單,購買的第一個產品是什么”的邏輯。 我在其他查詢中使用相同的邏輯。 如何將其分解為共享方法?

通常,對於代碼重用和IQueryables,我能夠做的是使IQueryable進入並生成IQueryable / IOrderedQueryable作為輸出的代碼。 使用這些函數,我可以使用可重用代碼構建LINQ表達式,該代碼仍然會延遲查詢,直到完全構造查詢。 在這里,由於我只有一個int(orderID),我不知道如何使它工作。

謝謝

很抱歉回答我自己的問題,但我找到了一個很好的解決方案。 我認為,根據你想要做的事情,有不同的方法來分解不同的LINQ表達式而不評估IQueryable。 所以我希望人們分享替代解決方案。

我的解決方案是為分解的查詢創建一個“視圖”。 我將其稱為視圖,因為它與SQL視圖有很多共同之處(從LINQ客戶端的角度來看)。 但是,與SQL視圖不同,它無法編入索引或持久保留列。 因此,使用此視圖成為瓶頸,使用實際的SQL視圖是合適的。

static public class MyDataContextExtension
{
    // The view exposes OrderSummary objects
    public class OrderSummary
    {
        public OrderID { get; set; }
        public string FirstProductListed { get; set; }
    }

    static public IQueryable<OrderSummary> OrderySummaryView(this MyDataContext db)
    {
         return (
              from O in db.Orders
              join OD in db.OrderDetails on O.OrderID equals OD.OrderID into OrderDetails
              let AProductBought = OrderDetails.First().Select(OD => OD.Product.ProductName)
              let TotalCost = OrderDetails.Aggregate(0
              select new OrderSummary()
              {
                  OrderID = OD.OrderID,
                  FirstProductListed = AProductBought.FirstOrDefault()
              };
    }
}

有了這個,我可以分解查詢的重復部分,用以下內容替換原始查詢:

var result = 
from T in db.Transactions
join OS in db.OrderSummaryView() on T.OrderID equals OS.OrderID
select new
{
  TransactionID = T.TransactionID,
  OrderID = T.OrderID,
  FirstProductBought = OS.FirstProductListed
};

您可以想象添加其他列...我認為一個很酷的事情是,如果您添加額外的列但不在最終選擇中使用它們,LINQ實際上不會從數據庫中查詢這些內容。

我們遇到了同樣的問題。 它不是開箱即用的支持,它是LOB應用程序的主要問題。 我最后編寫了一篇關於LINQ表達式重用的代碼項目文章,其中包括一個名為LinqExpressionPrjection的非常小的實用程序,它可以在投影中重用(包括匿名類型)。

這里找到文章。

您可以將投影重用的程序集作為nuget包獲取 ,源代碼可以在CodePlex上

你的帖子已經過了一段時間了。 我希望它對你有用。 如果沒有,也許是其他人閱讀這個帖子。

影響linq表達式的另一個重要方法是傳遞表達式,例如:

X GetSomeX(Expression<Func<Y, X>> map)
{
    return SourceOfYs.Select(map);
}

我通過查看巴拉克文章的文章得到了這個想法 - 即使他在這個主題上做了更多,我想我在這里再次提到這篇文章。 直接指出似乎是一個明顯的第一件事。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM