Entity Framework Core Dynamic Or Where Queries - gecko-8/devwiki GitHub Wiki
Sometimes you want to OR together a dynamic number of Where queries. For example, you want to search for results based on a dynamic list of selectable tags. Since you don't know the number of tags to search up front, you can't build a single Where clause that encompasses all possible options (without using Dynamic Linq).
- Add PredicateBuilder class to your project.
using System.Linq.Expressions;
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
- Use the PredicateBuilder to create a predicate containing your ORed tests, then add a single Where statement using the predicate. Here's an example searching strings using a dynamic number of search terms:
var testData = new List<string>
{
"Test string 1",
"Quick brown fox",
"Some other string",
"The fox is fast",
"Just some random text"
};
var searches = new List<string>
{
"string",
"fox"
};
// The type is the type of the objects we're querying (testData)
var predicate = PredicateBuilder.False<string>();
// Build up the predicate by iterating over our search terms
foreach(var search in searches)
predicate = predicate.Or(item => item.Contains(search));
// Perform the filter (Note the .Compile)
var results = testData.Where(predicate.Compile());
foreach(var result in results)
Console.WriteLine(result);