Linq has been around for a while now, and it is arguably a very powerful tool to have at your disposal in your development arsenal. It allows very quick and easy traversal of IEnumerable and IQueryable based objects that you would otherwise have to use a loop to work with. First let's take a look at how linq works verses a traditional loop.

Loop Example
public List<Post> GetDraftPosts()  
{
    List<Post> posts = _postService.GetPosts();
    List<Post> draftPosts = new List<Post>();
    foreach (var post in posts)
    {
        if (post.IsDraft)
        {
            draftPosts.Add(post);
        }
    }
    return draftPosts;
}
Linq IEnumerable Example
//At the top of the class make sure to add a using statement
using System.Linq;  
...
public List<Post> GetDraftPosts()  
{
    IEnumerable<Post> posts = _postService.GetPosts();
    Func<Post,bool> criteria = (x => x.IsDraft);
    return posts.Where(criteria).ToList();
}

What you see above is a delegate function written in lambda notation. The parameter of the Where() method is also referred to as a predicate. As you can see, linq can reduce the number of lines of code needed to produce the same result. However, this is a really poor approach to working with a data layer, because it would appear that the above code is looking up all posts, and then filtering down to what it needs. This is where IQueryable comes in.

IEnumerable vs IQueryable

IEnumerable is the interface that makes Linq To Objects possible. IQueryable is the interface that makes Linq To Sql possible. Both IQueryable and IEnumerable use deferred execution which means that the results will not be evaluated until they moment they are needed. The difference between the two is that IQueryable will be executed in the database if possible, and IEnumerable will bring back all rows of a table and then filter it down in memory. This has massive performance implications.

Linq with IQueryable

IQueryable uses predicates of type Expression<Func<T,bool> that are called expression trees. Expression trees allow you to define linq expressions that target sources of data that implement IQueryable to make requests against a database. This tree structure describes what a lambda expression does as opposed to just executing a delegate function, so that something like Linq To Sql can convert the expression to an equivalent sql statement. Let's refine our earlier example by using an expression tree and complicate the lookup a bit.

public List<Post> GetDraftPosts(int userId = 0, int userTypeId = 0)  
{
    Expression<Func<Post,bool>> criteria = new Expression<Func<Post,bool>>();
    if (userId > 0 && userTypeId > 0)
    {
        criteria = (x => x.IsDraft && x.UserId == userId && x.UserTypeId = userTypeId);
    }
    else if (userId > 0)
    {
        criteria = (x => x.IsDraft && x.UserId == userId);
    }
    else
    {
        criteria = (x => x.IsDraft);
    }
    //_postService.GetPosts() uses IQueryable under the hood, which is why we pass in an expression tree
    IEnumerable<Post> posts = _postService.GetPosts(criteria);
    return posts.ToList();
}

In the above example, the expression tree resembles very closely what we saw in the IEnumerable example, but the expression tree will be evaluated and converted into something an IQuerable datasource can use in the database. However, expression trees can result in cluttered looking branching logic where you repeat at least some part of the same logic multiple times. This is where a PredicateBuilder comes in.

Combining Expression Trees

If you start experimenting with expression trees, you will quickly find yourself in the scenario illustrated above. Out of the box, .NET makes combining expression trees very complicated. That's where this author's solution comes in very handy https://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/. Once implemented you'll have access to a wide array of extension methods for expression trees. Let's take a look at the above example again with the PredicateBuilder implemented.

public List<Post> GetDraftPosts(int userId = 0, int userTypeId = 0)  
{
    Expression<Func<Post,bool>> criteria = new Expression<Func<Post,bool>>();
    criteria = (x => x.IsDraft);
    //Append more criteria
    if (userId > 0)
    {
        criteria = criteria.And(x => x.UserId == userId);
    }
    //Append more criteria
    if (userTypeId > 0)
    {
        criteria = criteria.And(x => x.UserTypeId = userTypeId);
    }
    //_postService.GetPosts() uses IQueryable under the hood, which is why we pass in an expression tree
    IEnumerable<Post> posts = _postService.GetPosts(criteria);
    return posts.ToList();
}

Now we can add each additional piece of criteria independently of each other as opposed to build from the most specific situation backwards. The code becomes more readable and it is less likely that a developer will make a mistake by putting logic in the wrong order. One important thing to notice is that the expression tree object is set to itself plus the extension method. If you just call the extension method without setting the expression tree to itself you will end up with no change to the object.