469,306 Members | 1,987 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Share your developer knowledge by writing an article on Bytes.

Dynamic LINQ Where Clauses -- PredicateBuilder

Curtis Rutland
3,256 Expert 2GB
This isn't a full-blown article, just a quickie. But I couldn't pass up the opportunity to share this insight with people, because it made my coding life sooooooo much easier.

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

Its usefulness is situational, but I found it most valuable when I was building a searching application. I had no idea which parameters a user might include in their search. I didn't want to string-build a select statement, because I'd already created my LINQ to SQL classes, and I didn't want to do dynamic LINQ because to me the whole point of LINQ is type safety and IntelliSense.

So I found the PredicateBuilder. My favorite part of this is that it's not some big library that you have to download and include. It's a few lines of code that you can just paste into your own project:

Expand|Select|Wrap|Line Numbers
  1. using System;
  2. using System.Linq;
  3. using System.Linq.Expressions;
  4. using System.Collections.Generic;
  5.  
  6. public static class PredicateBuilder
  7. {
  8.   public static Expression<Func<T, bool>> True<T> ()  { return f => true;  }
  9.   public static Expression<Func<T, bool>> False<T> () { return f => false; }
  10.  
  11.   public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
  12.                                                       Expression<Func<T, bool>> expr2)
  13.   {
  14.     var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
  15.     return Expression.Lambda<Func<T, bool>>
  16.           (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
  17.   }
  18.  
  19.   public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
  20.                                                        Expression<Func<T, bool>> expr2)
  21.   {
  22.     var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
  23.     return Expression.Lambda<Func<T, bool>>
  24.           (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
  25.   }
  26. }
Add a namespace and dump that into your project, and you can use it.

The article explains how to use it better than I could. I did find one odd behavior: using foreach loops.

You would normally do this:
Expand|Select|Wrap|Line Numbers
  1. foreach(string s in stringCollection)
  2. {
  3.     whereClause = whereClause.Or(p => p.SomeString == s);
  4. }
However, for some reason, it seems to copy the pointer to "s" or something, and you end up with all the Or statements using the last value of s. To fix this, you do:
Expand|Select|Wrap|Line Numbers
  1. foreach(string s in stringCollection)
  2. {
  3.     string temp = s;
  4.     whereClause = whereClause.Or(p => p.SomeString == temp);
  5. }
Other than that, it works great.
May 12 '10 #1
0 24461

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

4 posts views Thread by BeSharp | last post: by
15 posts views Thread by EDBrian | last post: by
reply views Thread by EDBrian | last post: by
9 posts views Thread by =?Utf-8?B?RXZlcnQ=?= | last post: by
1 post views Thread by Lacutas | last post: by
4 posts views Thread by =?Utf-8?B?TWlrZSBDb2xsaW5z?= | last post: by
reply views Thread by Jay Douglas | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by suresh191 | last post: by
reply views Thread by harlem98 | last post: by
1 post views Thread by Geralt96 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.