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