问题
I often come across, in LINQ for Entity Framework, a pattern where I add a .Where
clause if a string value is specified, like:
IQueryable<Foo> query = Foos.AsQueryable()
if (!string.IsNullOrWhitespace(nameFilter)) query = query.Where(x => x.Name == name);
if (!string.IsNullOrWhitespace(addressFilter) != null) query = query.Where(x => x.Address == addressFilter );
if (!string.IsNullOrWhitespace(cityFilter) != null) query = query.Where(x => x.City == cityFilter );
// ...
I wanted to clean this up and avoid repeating the filter. I thought I could create an extension method:
public static IQueryable<T> WhereEqualIfSpecified<T>(
this IQueryable<T> query,
Expression<Func<T, string>> fieldDelegate,
string filterValue)
{
return string.IsNullOrWhiteSpace(filterValue)
? query
: query.Where(x => fieldDelegate(x) == filterValue); // not valid, see question below
}
So that I can instead change my code to:
IQueryable<Foo> query = Foos.AsQueryable()
.WhereEqualIfSpecified(x => x.Name, nameFilter)
.WhereEqualIfSpecified(x => x.Address, addressFilter)
.WhereEqualIfSpecified(x => x.City, cityFilter)
// ...
;
But I found that, in the WhereEqualIfSpecified
method above, fieldDelegate
must be compiled to a Func()
to be invoked against the entity source, which ruins the point of doing these steps, which would be executed in the database in my original code.
I am missing the last step of how to create a new Expression
from fieldDelegate
that can do a comparison, rather than just returning the string value. Will this approach work? How do I make the necessary Expression
in WhereEqualIfSpecified
to allow LINQ-to-Entities to execute it later?
回答1:
What you're trying to do here is to compose expressions. Expressions, unlike delegates, are a bit tricker to compose. Here is one implementation of how to compose expressions. Once you have that Compose
method you can write your extension method as:
public static IQueryable<T> WhereEqualIfSpecified<T>(
this IQueryable<T> query,
Expression<Func<T, string>> fieldExpression,
string filterValue)
{
return string.IsNullOrWhiteSpace(filterValue)
? query
: query.Where(fieldExpression.Compose(value => value == filterValue);
}
来源:https://stackoverflow.com/questions/40620704/how-can-i-build-logic-upon-supplied-logic-in-a-linq-to-entities-where-expression