【问题标题】:Expression Trees on DataTableDataTable 上的表达式树
【发布时间】:2015-05-15 22:02:41
【问题描述】:

我正在尝试使用ExpressionTrees 构建一个DataTable 过滤器,现在我创建了一个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 的东西,但我想看看这是如何用表达式树完成的 :)

希望有人能提供帮助。

【问题讨论】:

    标签: c# linq expression-trees dynamic-linq


    【解决方案1】:

    您的谓词必须经过编译才能在您的情况下使用,因为您在 IEnumerable&lt;&gt; 上进行操作。

    试试这个:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-11
        • 1970-01-01
        相关资源
        最近更新 更多