Dynamic clause where lambda

I am using the framework entity and I need to create dynamic expressions, for example:

var sel = Expression.Lambda<Func<TEntity, bool>>(propertyAccess, parameter);
var compiledSel = sel.Compile();
// sel = x.Name
// filter.Value = "John"
Repository.GetData.Where(item => compiledSel(item) != null && compiledSel(item).ToLower().StartsWith(filter.Value.ToString().ToLower()))

This works with IQueriable, but I need it to work with entity infrastructure.

That means I need to parse

item => compiledSel(item) != null && compiledSel(item).ToLower().StartsWith(filter.Value.ToString().ToLower())

eg,

x => x.Name != null && x.Name.StartsWith("John")

The reason I do this is because I have several objects that I want to be able to dynamically filter.

Any suggestions?

Edit:

The EF request itself starts here:

private IList<TEntity> GetCollection(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, object>>[] includes)
{
    return DbSet 
     .Where(where)
     .ApplyIncludes(includes)
     .ToList();
}

When I run the request, now the where where clause Param_0 => (((Invoke(value(....and I get an The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.error

+4
source share
2 answers

First of all, if it propertyAccessis an accessory to a string property, then

var sel = Expression.Lambda<Func<TEntity, bool>>(propertyAccess, parameter);

it should be

var sel = Expression.Lambda<Func<TEntity, string>>(propertyAccess, parameter);

-, Compile EF. , Expression, . "prototype" :

var selector = Expression.Lambda<Func<TEntity, string>>(propertyAccess, parameter);

var value = filter.Value.ToString().ToLower();

Expression<Func<string, bool>> prototype = 
    item => item != null && item.ToLower().StartsWith(value);

var predicate = Expression.Lambda<Func<T, bool>>(
    prototype.Body.ReplaceParameter(prototype.Parameters[0], selector.Body), 
    selector.Parameters[0]);

:

public static class ExpressionUtils
{
    public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
    {
        return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
    }

    class ParameterReplacer : ExpressionVisitor
    {
        public ParameterExpression Source;
        public Expression Target;
        protected override Expression VisitParameter(ParameterExpression node)
        {
            return node == Source ? Target : base.VisitParameter(node);
        }
    }
}
+3

Dynamic Linq:

Repository.People.Where("Name != null && Name.StartsWith(\"John\")")

https://www.nuget.org/packages/System.Linq.Dynamic

+1

Source: https://habr.com/ru/post/1652846/


All Articles