重构 LINQ IQueryable 表达式以删除查询的重复部分
我有一些具有冗余的 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),我不知道如何让它工作。
谢谢
I have some linq queries that have redundancy I'd like to factor out a single piece of code. These are join experssions that are IQueryable, and its important I don't cause the query to be evaluated earlier than it would be without the refactoring.
Here is a simplified query:
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
};
What I want to factor out is th logic "given an order, what is the first product bought". I am using the same logic in other queries. How can I factor it out into a shared method?
Generally, for code reuse and IQueryables, what I've been able to do is code that takes an IQueryable going in and produces an IQueryable/IOrderedQueryable as output. With such functions I can build up LINQ expressions with reusable code that still defer query until the query is fully constructed. Here, since I only have an int (the orderID) I'm not sure how to make it work.
thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
很抱歉回答我自己的问题,但我找到了一个很好的解决方案。 我认为,根据您想要执行的操作,有不同的方法可以在不评估 IQueryable 的情况下分解出不同的 LINQ 表达式。 所以我希望人们分享替代解决方案。
我的解决方案是为分解的查询创建一个“视图”。 我将其称为视图是因为它与 SQL 视图有很多共同点(从 LINQ 客户端的角度来看)。 但与 SQL 视图不同的是,它无法建立索引或保留列。 因此使用这个视图成为瓶颈,使用实际的 SQL 视图是合适的。
有了这个,我可以提取查询的重复部分,用以下内容替换原始查询:
您可以想象添加其他列...我认为一件很酷的事情是,如果您添加额外的列但不使用它们在您的最终选择中,LINQ 实际上不会从数据库中查询这些内容。
Sorry to answer my own question, but I found a good solution. I think though that depending on what you're trying to do, there are different way to factor out different LINQ expressions without evaluating the IQueryable. So I hope people share alternative solutions.
My solution was to create a "view" for the factored out query. I call it a view because it has a lot in common with a SQL view (from the perspective of a LINQ client). Unlike a SQL view though, it cannot be indexed or have columns persisted. So using this view becomes a bottleneck, it would be appropriate to use an actual SQL view.
With this, I can factor out the duplicated portion of the query, replacing the original query with the following:
You can imagine other columns being added... I think one cool thing is that if you add extra columns but don't use them in your final select, LINQ won't actually query for those things from the database.
我们有同样的问题。 它不受开箱即用的支持,这是 LOB 应用程序的一个主要问题。 我最终写了一篇关于 LINQ 表达式重用的代码项目文章,其中包括一个名为 LinqExpressionPrjection 的非常小的实用程序,它支持在投影中重用(包括匿名类型)。
此处查找文章。
您可以将用于投影重用的程序集作为 nuget 包 获取,源位于 CodePlex。
自从你发帖以来已经过去了一段时间了。 我希望它仍然对你有帮助。 如果没有,也许对于其他阅读此帖子的人来说。
We had the same problem. It is not supported out of the box and it is a major problem for LOB applications. I ended up writing a code-project article about LINQ expressions reuse, including a very small utility called LinqExpressionPrjection that enables the reuse in projections (including into anonymous types).
Find the article here.
You can get the assembly for the projection reuse as a nuget package and the source is on CodePlex.
Some time has passed since your post. I hope it is still helpful for you. If not, maybe for others reading this thread.
分解 linq 表达式的另一个重要方法是传递表达式,例如:
我通过研究 Barak 的文章得到了这个想法 - 尽管他在这个主题上做了更多的工作,但我想我在这里再次提到了这篇文章。 这似乎是显而易见的首先要直接指出的事情。
Another important way to factor linq expressions is to pass expressions around, for example:
I got the idea by looking into the article of Barak's article - and even though he does a bit more on that topic, I thought I mention this piece again here. It seems to be an obvious first thing to point out directly.