title: How to combine multiple Expression<Func<T, bool>> into a single expression to execute against DbContext?
body: <p>I'm trying to create a way to allow users of my app to create their own filter views of data. To do that I'm composing a list of Key-Operator-Value pairs which I then try, after multiple steps, to parse into an expression to use with a <code>Where</code> call. So far, I can get to a point where I have the expressions created, but I can't figure out how to merge them into a single expression.</p>
  
  <p>Could someone point me in the right direction on how to do so? From reading similar posts online, I've settled on trying to do it using the LINQKit <code>PredicateBuilder</code>, but all I'm getting back is the initial starting predicate. Here's the code I have so far, it is by no means final, I'm just prototyping it in LINQPad:</p>
  
  <pre><code>void Main() {
      //  1. Create form post object
      var query = new QueryEdit {
          Filters = new List&lt;Filter&gt; {
              new Filter {
                  Id = 1,
                  Key = "Name",
                  Operator = "=",
                  Value = "New York"
              },
              new Filter {
                  Id = 2,
                  Key = "Name",
                  Operator = "!=",
                  Value = "Boston"
              },
              new Filter {
                  Id = 3,
                  Key = "Name",
                  Operator = "=",
                  Value = "Washington"
              }
          },
          FilterClause = "1 AND 3 OR 2 OR 4"
      };
  
      //  2. Compose filter groups
      var filterGroups = GetFilterGroups(query);
  
      //  3. Compose expression groups
      var expressionGroups = GetExpressionGroups&lt;Region&gt;(filterGroups);
  
      expressionGroups.Dump();
  
      //  4. Compose full expression
      var expression = GetExpression(expressionGroups);
  
      expression.Dump();
  
      //  5. Serialize expression to blob
      //  6. Deserialize blob to expression
      //  7. Execute expression against db
  }
  
  static IEnumerable&lt;FilterGroup&gt; GetFilterGroups(
      QueryEdit query) {
      //  The parentheses are meaningless, so they need to be removed.
      //  The groups are all conditions with ANDs, separated by ORs.
  
      return query.FilterClause.Replace(")", string.Empty).Replace("(", string.Empty).Split(new[] { "OR" }, StringSplitOptions.None).Select(
          fc =&gt; new FilterGroup {
              Filters = fc.Split(new[] { "AND" }, StringSplitOptions.None).Select(
                  i =&gt; {
                      var id = Convert.ToByte(i);
  
                      return query.Filters.SingleOrDefault(
                          f =&gt; f.Id == id);
                  }).Where(
                  f =&gt; f != null).OrderBy(
                  f =&gt; f.Id)
          }).Where(
          fg =&gt; fg.Filters.Any());
  }
  
  static IEnumerable&lt;IEnumerable&lt;Expression&lt;Func&lt;T, bool&gt;&gt;&gt;&gt; GetExpressionGroups&lt;T&gt;(
      IEnumerable&lt;FilterGroup&gt; filterGroups) {
      var type = typeof(T);
      var parameter = Expression.Parameter(type);
  
      return filterGroups.Select(
          fg =&gt; {
              return fg.Filters.Select(
                  f =&gt; {
                      var left = Expression.Property(parameter, type.GetProperty(f.Key));
                      var right = Expression.Constant(f.Value);
                      var body = GetExpressionBody(f.Operator, left, right);
  
                      if (body == null) {
                          return null;
                      }
  
                      return Expression.Lambda&lt;Func&lt;T, bool&gt;&gt;(body, parameter);
                  }).Where(
                  e =&gt; e != null);
          });
  }
  
  static object GetExpression&lt;T&gt;(
      IEnumerable&lt;IEnumerable&lt;Expression&lt;Func&lt;T, bool&gt;&gt;&gt;&gt; expressionGroups) {
      var predicate = PredicateBuilder.True&lt;T&gt;();
  
      foreach (var expressionGroup in expressionGroups) {
          var expression = GetPredicateForGroup&lt;T&gt;(expressionGroup);
  
          predicate.Or(expression);
      }
  
      return predicate;
  }
  
  static Expression&lt;Func&lt;T, bool&gt;&gt; GetPredicateForGroup&lt;T&gt;(
      IEnumerable&lt;Expression&lt;Func&lt;T, bool&gt;&gt;&gt; expressionGroup) {
      var predicate = PredicateBuilder.True&lt;T&gt;();
  
      foreach (var expression in expressionGroup) {
          predicate.And(expression);
      }
  
      return predicate;
  }
  
  static Expression GetExpressionBody(
      string @operator,
      Expression left,
      Expression right) {
      switch (@operator) {
          case "=":
              return Expression.Equal(left, right);
          case "!=":
              return Expression.NotEqual(left, right);
          case "&gt;":
              return Expression.GreaterThan(left, right);
          case "&gt;=":
              return Expression.GreaterThanOrEqual(left, right);
          case "&lt;":
              return Expression.LessThan(left, right);
          case "&lt;=":
              return Expression.LessThanOrEqual(left, right);
          default:
              return null;
      }
  }
  
  sealed class QueryEdit {
      public IEnumerable&lt;Filter&gt; Filters { get; set; }
      public string FilterClause { get; set; }
      public int Id { get; set; }
      public string Name { get; set; }
  }
  
  sealed class Filter {
      public byte Id { get; set; }
      public string Key { get; set; }
      public string Operator { get; set; }
      public object Value { get; set; }
  }
  
  sealed class FilterGroup {
      public IEnumerable&lt;Filter&gt; Filters { get; set; }
  }
  </code></pre>
  
  <p>I'm also open to other suggestions on how to accomplish this, or overall improvements. Thanks in advance!</p>