Entity Framework Core Dynamic Or Where Queries - gecko-8/devwiki GitHub Wiki

Up

Problem

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).

Solution

  1. 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);
    }
}
  1. 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);

Source

⚠️ **GitHub.com Fallback** ⚠️