I am trying to write condition based on expression. I have two classes Test1 and Test2.
public class Test1<TEntity, TProperty>
{
public IQueryable<TEntity> Test(
IQueryable<TEntity> queryable,
Expression<Func<TEntity, TProperty>> expression,
TProperty value
)
{
MemberExpression memberExpression = (MemberExpression)(expression.Body);
var propName = memberExpression.Member.Name;
// Cannot apply operator '>' to operands of type 'P' and 'P'
queryable = queryable.Where(e => EF.Property<TProperty>(e, propName) > value));
return queryable;
}
}
public class Test2<TEntity, TProperty>
where TProperty : IComparable
{
public IQueryable<TEntity> Test(
IQueryable<TEntity> queryable,
Expression<Func<TEntity, TProperty>> expression,
TProperty value
)
{
MemberExpression memberExpression = (MemberExpression)(expression.Body);
var propName = memberExpression.Member.Name;
// This one compiles
queryable = queryable.Where(e => EF.Property<TProperty>(e, propName).CompareTo(value) > 0);
return queryable;
}
}
First one (Test1) tries to compare values with >
but it does not compile. Second one (Test2) declares generic type as IComparable and uses .CompareTo() method inside where condition. This one compiles but on runtime it throws:
The LINQ expression 'DbSet<SortableEntity>
.Where(s => s.IsDeleted == False)
.Where(s => EF.Property<long>((object)s, "Id").CompareTo((object)__value_0) > 0)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync()
Is it possible to somehow write custom condition based on expression? I want property/member expression to be passed by user and then decide what condition to apply to IQueryable.
CodePudding user response:
Well, EF.Property
is last thing that you have to use in such situation. You have property, even correct body - use this:
public class Test1<TEntity, TProperty>
{
public IQueryable<TEntity> Test(
IQueryable<TEntity> queryable,
Expression<Func<TEntity, TProperty>> expression,
TProperty value
)
{
var predicateLambda = Expression.Lambda<Func<TEntity, bool>>(
Expression.GreaterThan(expression.Body, Expression.Constant(value, typeof(TProperty))),
expression.Parameters[0]);
queryable = queryable.Where(predicateLambda);
return queryable;
}
}