Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build Expression to filter data EF Core

I need to reuse available expression:

Expression<Func<Picture, int>> selector = o => o.EntityId;

And build expression for Where:

Expression<Func<Picture, bool>> filter = w => w.EntityId > 5;

How can I build such an expression?

Next operation won't be executed on the client side, am I right?

var collection = _dbContext.Pictures.Where(filter).ToList();
like image 408
Pavel Avatar asked Sep 07 '26 21:09

Pavel


1 Answers

I finally figured out how to build an expression dynamically:

Expression<Func<Picture, int>> selector = o => o.EntityId;

var parameter = Expression.Parameter(typeof(Picture));

// get property name
if (!(selector.Body is MemberExpression memberExpression))
{
    memberExpression = ((UnaryExpression)selector.Body).Operand as MemberExpression;
}
var propertyName = memberExpression.ToString().Substring(2);

var expressionParameter = Expression.Property(parameter, propertyName);
var expressionBody = Expression.GreaterThan(expressionParameter, Expression.Constant(5, typeof(int)));

var filter = Expression.Lambda<Func<Picture, bool>>(expressionBody, parameter);
var collection = _dbContext.Pictures.Where(filter).ToList();

Generic example:

var filter = CreateFilter<Picture, int>(o => o.EntityId, 5);
var collection = _dbContext.Pictures.Where(filter).ToList();

private Expression<Func<TData, bool>> CreateFilter<TData, TKey>(Expression<Func<TData, TKey>> selector, TKey valueToCompare)
{
    var parameter = Expression.Parameter(typeof(TData));
    var expressionParameter = Expression.Property(parameter, GetParameterName(selector));

    var body = Expression.GreaterThan(expressionParameter, Expression.Constant(valueToCompare, typeof(TKey)));
    return Expression.Lambda<Func<TData, bool>>(body, parameter);
}

private string GetParameterName<TData, TKey>(Expression<Func<TData, TKey>> expression)
{
    if (!(expression.Body is MemberExpression memberExpression))
    {
        memberExpression = ((UnaryExpression)expression.Body).Operand as MemberExpression;
    }

    return memberExpression.ToString().Substring(2);
}

Thanks to David’s response about Prohibit client-side evaluation, I was able to verify that filtering doesn't executed on the client

like image 84
Pavel Avatar answered Sep 11 '26 19:09

Pavel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!