我有一些具有冗余的 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),我不知道如何让它工作。
thanks
很抱歉回答我自己的问题,但我找到了一个很好的解决方案。我认为,根据您想要执行的操作,有不同的方法可以在不评估 IQueryable 的情况下分解出不同的 LINQ 表达式。所以我希望人们分享替代解决方案。
我的解决方案是为分解的查询创建一个“视图”。我将其称为视图是因为它与 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 实际上不会从数据库中查询这些内容。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)