Home > Mobile >  How to create a dynamic linq query chained with a or operator from a user input?
How to create a dynamic linq query chained with a or operator from a user input?

Time:01-14

The library I used is : Microsoft.EntityFrameworkCore.DynamicLinq

I already managed to do it with an "and" operator, simply by chaining the "Where" in PrepareQuerySearch(Search search) :

public class FilterAnd
{
    public string Field { get; set; } = string.Empty;
    public string Value { get; set; } = string.Empty;
    public Criteria Criteria { get; set; }

    public string GetLinqQuery() { 
        string query = string.Empty;
        switch (this.Criteria)
        {
            case Criteria.Equal:
                query = $"{Field} == @0";
                break;
            case Criteria.NotEqual:
                query = $"{Field} != @0";
                break;
            case Criteria.GreaterThan:
                query = $"{Field} > @0";
                break;
            case Criteria.LessThan:
                query = $"{Field} < @0";
                break;
            case Criteria.GreaterThanOrEqual:
                query = $"{Field} >= @0";
                break;
            case Criteria.LessThanOrEqual:
                query = $"{Field} <= @0";
                break;
            case Criteria.Like:
            case Criteria.In:
            case Criteria.NotLike:
            case Criteria.NotIn:
                query = $"!{Field}.Contains(@0)";
                break;
            case Criteria.IsNull:
                query = $"{Field} == null";
                break;
            case Criteria.IsNotNull:
                query = $"{Field} != null";
                break;
        }
        return query;
    }
}

public class Search
{
    public List<FilterAnd> FiltersAnd { get; set; } = new List<FilterAnd>();
    public List<OrderBy> OrderBy { get; set; } = new List<OrderBy>();
    public int Skip { get; set; } = 0;
    public int Take { get; set; } = 2000;
}

public IQueryable<T> PrepareQuerySearch(Search search)
{
    string delimiter = "§^_^§";
    var query = _dbContext.Set<T>().AsQueryable();
    foreach (var filter in search.FiltersAnd)
    {
        switch (filter.Criteria)
        {
            case Criteria.In:
            case Criteria.NotIn:
                query = query.Where(filter.GetLinqQuery(), filter.Value.Split(delimiter));
                break;
            default:
                query = query.Where(filter.GetLinqQuery(), filter.Value);
                break;
        }
    }
    return query;
}

But what if I want in instead of search.FilterAnd a search.FilterOr ?

I also tried to use Expressions from linq but I was wondering if there is not a easier solution to implement this.

Edit 2023.01.10

I will try to build it with expressions for now but it will be a lot of work. Example with Equal :

public static IQueryable<T> WhereEqual<T>(this IQueryable<T> source, string propertyName, string propertyValue)
            {
                var param = Expression.Parameter(typeof(T));
                var prop = typeof(T).GetProperty(propertyName);
                var condition =
                    Expression.Lambda<Func<T, bool>>(
                        Expression.Equal(
                            Expression.Property(param, propertyName),
                            Expression.Constant(propertyValue, prop.PropertyType)
                        ),
                        param
                    );
                return source.Where(condition);
            }

CodePudding user response:

Resolved by using dynamic linq from the library mentionned in question :

DynamicExpressionParser.ParseLambda<T, bool>(new ParsingConfig(), true, filter.GetLinqQuery(), filter.Value)

Then you can simply join them by using predicates :

Where("@0(it) and @1(it)", e1, e2);
  • Related