【问题标题】:How to write condition based on expression?如何根据表达式编写条件?
【发布时间】:2021-12-24 05:46:39
【问题描述】:

我正在尝试根据表达式编写条件。 我有两个类 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)尝试将值与&gt; 进行比较,但它无法编译。第二个(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()

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

【问题讨论】:

    标签: linq entity-framework-core ef-core-3.1


    【解决方案1】:

    好吧,EF.Property 是您在这种情况下必须使用的最后一件事。你有财产,甚至是正确的身体——使用这个:

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

    【讨论】:

    • 您的代码由于某种原因无法编译:得到“无法解析方法 'GreaterThan(System.Linq.Expressions.Expression, System.Linq.Expressions.ConstantExpression, System.Type)',候选者是: ...”
    • 已修复,从内存中写入,括号出错。
    • 谢谢,即使没有typeof(TProperty) 也能正常工作。只需Expression.GreaterThan(expression.Body, Expression.Constant(value))
    • 是的,Expression.Constant 可以从 value 中获取 type,如果它不为 null。但如果存在,最好传递此信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-31
    • 2017-05-31
    • 1970-01-01
    • 2021-03-23
    • 1970-01-01
    相关资源
    最近更新 更多