数据表上的表达式树

本文关键字:表达式 数据表 | 更新日期: 2023-09-27 17:49:24

我正在尝试与ExpressionTrees建立一个数据表过滤器,现在我制作了一个QueryBuilder助手类,如下所示。调用将像这样:

                var pb = PredicateBuilder.True<DataRowCollection>();
                int i = 0;
                foreach (var key in keys)
                {
                    pb.And<DataRowCollection>(QueryBuilder.CompareProperty<DataRowCollection>(key.Code, value[key.Code]));
                    i++;
                }
                var qs = qt.Where(pb);

现在的问题是,我得到一个错误,像这样:

'System.Data.EnumerableRowCollection<System.Data.DataRow>' does not contain a definition for 'Where' and the best extension method overload 'System.Data.EnumerableRowCollectionExtensions.Where<TRow>(System.Data.EnumerableRowCollection<TRow>, System.Func<TRow,bool>)' has some invalid argument
Argument 2: cannot convert from 'System.Linq.Expressions.Expression<System.Func<System.Data.DataRowCollection,bool>>' to 'System.Func<System.Data.DataRow,bool>'

助手类:

public class QueryBuilder
{
    public static Expression<Func<T, bool>> Compare<T>(T rhs, ExpressionType op)
    {
    var lhsParam = Expression.Parameter(typeof(T), "x");
    var rhsParam = Expression.Constant(rhs);
    var binaryExp = Expression.MakeBinary(op, lhsParam, rhsParam);
    var theLambda = Expression.Lambda<Func<T, bool>>(binaryExp, lhsParam);
    return theLambda;
}
public static Expression<Func<T, bool>> Between<T>(T lower, T upper)
{
    var predicateInner = PredicateBuilder.True<T>();
    predicateInner = predicateInner.And(Compare<T>(lower, ExpressionType.GreaterThan));
    predicateInner = predicateInner.And(Compare<T>(upper, ExpressionType.LessThan));
    return predicateInner;
}
public static Expression<Func<T,bool>>  CompareProperty<T>(string propertyName, dynamic criteria)
{
    ParameterExpression pe = Expression.Parameter(typeof(T), "t");
    Expression np = Expression.Property(pe, propertyName);
    ConstantExpression value = Expression.Constant(criteria);
    Expression eq = Expression.Equal(np, value);
    var filter = Expression.Lambda<Func<T, bool>>(eq, pe);
    return filter;
}
}
public static class PredicateBuilder
{
    public static Expression<Func<T, bool>> True<T>() { return f => true; }
    public static Expression<Func<T, bool>> False<T>() { return f => false; }
    public static Expression<Func<T, bool>> True<T>(IQueryable<T> query) { return f => true; }
    public static Expression<Func<T, bool>> False<T>(IQueryable<T> query) { return f => false; }

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                              Expression<Func<T, bool>> expr2)
    {
        var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>
           (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
    }
    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                               Expression<Func<T, bool>> expr2)
    {
        var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>
           (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
    }
}

我知道有一种叫做动态Linq的东西,但我想看看这是如何用表达式树完成的:)

希望有人能帮忙

数据表上的表达式树

您的谓词必须被编译以在您的情况下可用,因为您在IEnumerable<>上操作。

试试这个:

var qs = qt.Where(pb.Compile());

不需要lambda表达式在内存中搜索。不要使您的生活过于复杂,只需创建委托(Func<T,>)并使用它们,编写、处理和调试要容易得多!