Reputation: 18237
I like to reuse expressions for DRY reasons, but how do I reuse the expressions within a LINQ statement?
e.g.
I have
public static class MyExpressions {
public static Expression<Func<Product,bool>> IsAGoodProduct() {
return (p) => p.Quality>3;
}
}
And would like to use that in LINQ statements, so
var goodProds = from p in dataContext.Products
where ????? // how do I use IsAGoodProduct here?
select p;
Sure, I could use the IQueryableExtension.Where function, but that would make joins and other functions alot uglier for more complex queries.
Is this possible or is it a limitation of LINQ?
Upvotes: 26
Views: 8192
Reputation: 17356
By the way, I've come across this useful article which explains how you can create dynamic LINQ Queries that reference functions wrapped as Expressions using a custom ToExpandable() extension method. The solution provided can be used within the various parts of a LINQ Query all while preserving the use of comprehension syntax instead of resorting to lambda syntax.
Upvotes: 1
Reputation: 1883
I had the same problem and wanted to preserve the ability to use extension methods within the query syntax (as with ordinary supported functions...). A solution might be this library (spoiler: I‘m the author).
You just implement the method to reuse twice, once for general use and once for queries.
public static class MyFunctions {
[InjectLambda]
public static bool IsAGoodProduct(Product product) {
return product.Quality>3;
}
public static Expression<Func<Product,bool>> IsAGoodProduct() {
return (p) => p.Quality>3;
}
}
The actual query can then look like expected.
var goodProds = from p in dataContext.Products.ToInjectable()
where p.IsAGoodProduct()
select p;
The ToInjectable
call creates a lightweight proxy, which replaces the IsAGoodProduct
method call (if marked accordingly) with the desired lambda expression. Thus, you can use extension methods wherever within the query -- parameterized methods work as well.
Upvotes: 5
Reputation: 171
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.
Upvotes: 3
Reputation: 32698
If you move from the LINQ syntactic sugar it is possible:
var goodProds = dataContext.Products.Where(MyExpressions.IsAGoodProduct());
Without it, it isn't possible.
There's nothing to stop you mixing the two styles to build a single query though.
Example:
var goodProds = from p in dataContext.Products
.Where(MyExpressions.IsAGoodProduct())
group p by p.Category into g
select new {Category = g.Key, ProductCount = g.Group.Count()};
Upvotes: 24