如何根据表达式编写条件?

How to write condition based on expression?

我正在尝试根据表达式编写条件。 我有两个 类 Test1 和 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;
    }
}

第一个 (Test1) 尝试将值与 > 进行比较,但未编译。第二个 (Test2) 将泛型类型声明为 IComparable 并在 where 条件内使用 .CompareTo() 方法。这个编译但在运行时抛出:

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

是否可以根据表达式以某种方式编写自定义条件?我希望 property/member 表达式由用户传递,然后决定将什么条件应用于 IQueryable。

好吧,EF.Property 是您在这种情况下必须使用的最后一件事。你有 属性,甚至正确 body - 使用这个:

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