0

I'm using C# 2010 .NET 4.0 and I have a List<T> collection called returns that I need to build a dynamic LINQ query on.

I'm utilizing the Predicate Builder referenced here.

This works fine if I have 1 filter criteria, but if I have 2 or more, then, when the query.compile() is called, I get this error:

variable 'tmp' of type 'Check21Tools.IncomingReturn' referenced from scope '', but it is not defined

Code:

  Expression<Func<Check21Tools.IncomingReturn, bool>> query = null;

  bool hasFilterItems = false;
  if (filterArray != null)
  {
    foreach (string s in filterArray)
    {
      if (s == string.Empty)
      { break; }
      else
      {
        hasFilterItems = true;
        Int64 id = Int64.Parse(s);
        query = query.Or(tmp => tmp.ID == id);
      }

    }
  }
  if (hasFilterItems)
  {
    returns = returns.Where(query.Compile()).CreateFromEnumerable
                  <Check21Tools.IncomingReturns, Check21Tools.IncomingReturn>();
  } 

Code:

 public static Expression<Func<T, bool>> Or<T>(
     this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
 {
     if (expr1 == null) return expr2;

     return Expression.Lambda<Func<T, bool>>
         (Expression.OrElse(expr1.Body, expr2.Body), expr1.Parameters);

 }
Phil
  • 42,255
  • 9
  • 100
  • 100
Shawn Hollon
  • 9
  • 1
  • 5
  • If you're using `List`, why are you building up an `Expression<>` at all? You can just use straight delegates. – Jon Skeet Mar 20 '13 at 17:15
  • Can you give me an example of doing that dynamically? My `filterArray` object holds the id's I need to filter for. – Shawn Hollon Mar 20 '13 at 17:18
  • See http://stackoverflow.com/questions/7094930/linq-to-objects-predicate-builder for a version of PredicateBuilder which doesn't use expression trees. – Jon Skeet Mar 20 '13 at 17:18
  • -1: You're not using the PredicateBuilder you linked to. The PredicateBuilder you linked to gives a different `Or` method. –  Mar 20 '13 at 17:18
  • @ShawnHollon So what do you actually want to do? What should the result of your query be? – Servy Mar 20 '13 at 17:20
  • So, say my `returns` object has 10 items. and I've generated a list of "ID's" dynamically that I want to filter on. I want to filter my `returns` from the 10 to say 2 items. it should work the same as this `returns = returns.where(tmp=>tmp.ID == 110 || tmp.ID == 111)` @hvd, the difference in the OR method is the ORElse is the equivalnt to this || instead of the OR method using the bitwise of | – Shawn Hollon Mar 20 '13 at 17:24
  • You shouldn't need Predicate Builder for that. You just need an IN clause. http://stackoverflow.com/q/423840 and http://wekeroad.com/2008/02/27/creating-in-queries-with-linq-to-sql/ – Robert Harvey Mar 20 '13 at 17:27
  • @RobertHarvey He's doing LINQ to Objects. – Servy Mar 20 '13 at 17:34
  • @RobertHarvey So it's not a LINQ to SQL query... – Servy Mar 20 '13 at 17:34
  • @Servy: It doesn't matter. Linq to SQL returns IEnumerables, and that's all Rob Conery's article is really talking about. The first link I provided works too. – Robert Harvey Mar 20 '13 at 17:35
  • I've stumbled across an updated version of the predicate builder to work on List objects `public static Expression> Or(this Expression> expr1, Expression> expr2) { if (expr1 == null) return expr2; var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast()); return Expression.Lambda> (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters); }` – Shawn Hollon Mar 20 '13 at 17:35
  • Don't post code in comments. As you can see, it's unreadable. if this is an answer, post it as an answer. If it is an update to your question, click `edit` and paste the code into your question. – Robert Harvey Mar 20 '13 at 17:36
  • I do appreciate the input. – Shawn Hollon Mar 20 '13 at 17:36
  • @Robert harvy, the system won't let me post an answer so soon since I'm a New member. i will be posing this as an answer as soon as the system lets me. Apparently, I have 7 hours to wait. – Shawn Hollon Mar 20 '13 at 17:37
  • @ShawnHollon: The time delay is imposed on everyone, not just new users. I put it in an answer for you. – Robert Harvey Mar 20 '13 at 17:39
  • Also, note the comments I made about the `IN` clause. If you already have a list of ID's, you don't need Predicate Builder; you can just use `Contains()`. – Robert Harvey Mar 20 '13 at 17:41

1 Answers1

0

[The OP has] stumbled across an updated version of the predicate builder that works on List<T> objects:

public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
  {
     if (expr1 == null) return expr2;
     var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
     return Expression.Lambda<Func<T, bool>>
              (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
  }
Joel Harris
  • 1,966
  • 3
  • 20
  • 32
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501