你的位置:首页 > ASP.net教程

[ASP.net教程]通过LINQ表达式树动态构建查询条件


第一种方法:

public static class PredicateExtensions  {    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>> Or<T>(this Expression<Func<T, bool>> expression1,      Expression<Func<T, bool>> expression2)    {      var invokedExpression = Expression.Invoke(expression2, expression1.Parameters          .Cast<Expression>());      return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression),      expression1.Parameters);    }    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1,        Expression<Func<T, bool>> expression2)    {      var invokedExpression = Expression.Invoke(expression2, expression1.Parameters         .Cast<Expression>());      return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body,          invokedExpression), expression1.Parameters);    }  }

第二种方法:

  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<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)    {      // build parameter map (from parameters of second to parameters of first)      var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);      // replace parameters in the second lambda expression with parameters from the first      var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);      // apply composition of lambda expression bodies to parameters from the first expression       return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);    }    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)    {      return first.Compose(second, Expression.And);    }    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)    {      return first.Compose(second, Expression.Or);    }  }

注意,经我实际应用,发现第一种方法PredicateExtensions类有个缺陷,就是仅适合在DbDataContext中使用,若用在EntityContext中,则会报错:LINQ to Entities 不支持 LINQ 表达式节点类型“Invoke”。而使用第二种方法则不会有这个问题,至于问题的根源我还没有找到原因,还望高手指教,谢谢!