2012-01-03 68 views
1

在SQL我可以寫這樣的語句:
SELECT * FROM Clients Where (clientId = 1 and lastname = 'smith' or partnerlastname='jones') OR (clientId = 2 and lastname = 'brown' or partnerlastname='campbell')
OR (clientId = 3 and lastname = 'higgins' or partnerlastname='cholmondely')
NHibernate的如何我代表的集合或謂詞

我試圖使用LINQ通過謂詞的每一個可枚舉做在nhhibernate類似的東西的ORs。

我似乎可以爭論c#足以讓它工作,雖然...是可能的嗎?我將如何解決這個問題?

回答

2

我會用一個謂語器類是這樣的:

http://www.albahari.com/nutshell/predicatebuilder.aspx

public static class PredicateBuilder 
    { 
     /// <summary> 
     /// Creates a predicate that evaluates to true. 
     /// </summary> 
     public static Expression<Func<T, bool>> True<T>() { return param => true; } 

     /// <summary> 
     /// Creates a predicate that evaluates to false. 
     /// </summary> 
     public static Expression<Func<T, bool>> False<T>() { return param => false; } 

     /// <summary> 
     /// Creates a predicate expression from the specified lamda expression. 
     /// </summary> 
     public static Expression<Func<T, bool>> Create<T>(Expression<Func<T, bool>> predicate) { return predicate; } 

     /// <summary> 
     /// Combines the first predicate with the second using the logical "and". 
     /// </summary> 
     public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) 
     { 
      return first.Compose(second, Expression.AndAlso); 
     } 

     /// <summary> 
     /// Combines the first predicate with the second using the logical "not". 
     /// </summary> 
     public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expr) 
     { 
      return Expression.Lambda<Func<T, bool>>(Expression.Not(expr.Body), expr.Parameters); 
     } 

     /// <summary> 
     /// Combines the first predicate with the second using the logical "or". 
     /// </summary> 
     public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) 
     { 
      return first.Compose(second, Expression.OrElse); 
     } 

     /// <summary> 
     /// Combines the first expression with the second using the specified merge function. 
     /// </summary> 
     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); 
     } 

     class ParameterRebinder : ExpressionVisitor 
     { 
      readonly Dictionary<ParameterExpression, ParameterExpression> map; 

      ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map) 
      { 
       this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>(); 
      } 

      public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp) 
      { 
       return new ParameterRebinder(map).Visit(exp); 
      } 

      protected override Expression VisitParameter(ParameterExpression p) 
      { 
       ParameterExpression replacement; 

       if (map.TryGetValue(p, out replacement)) 
       { 
        p = replacement; 
       } 

       return base.VisitParameter(p); 
      } 
     } 
    }