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
Where
: it should beIQueryable
(basically saying that the query has not been materialized) , and the result ofToList
should beIEnumerable
, meaning that it will materialize the query the whole query that has been built. Note that sometimes, Entity Framework (or rather, the DB SQL adapter that is used) may not know how to translate some condition, but you should get a warning, sometimes during execution (so keep an eye on your console!). – Tynes