Home > Programming > Dynamically composing predicates

Dynamically composing predicates

Typically when I’m using LINQ to filter collections, my conditions aren’t very complex and usually contain a single boolean condition. For example, if I wanted to filter a collection of WorkItems, I’ll use the Where extension method:

workItems.Where(x => x.Status == Status.Done);

I’ve come across a scenario where I needed to chain multiple “OR” expressions. It’s easy to chain multiple “OR” expressions during compile time:

workItems.Where(x => x.Status == Status.Done || x.Status == Status.Processing);

However, this is difficult to do if the conditions are determined at runtime. In an application, I’m asking the user to select from a list of statuses. They may select one or more statuses.

Since I still work a lot with stored procedures, I’ll typically use dynamic SQL to generate a WHERE clause if these status were stored in a database. But with a collection, this isn’t easy to do without some help.

After looking around, I stumbled across the PredicateBuilder class that ships as part of LINQKit.

The PredicateBuilder allows me to easily chain multiple “AND” and “OR” conditions together at runtime. I can append an “OR” condition to the predicate if the respective checkbox is checked:

var predicate = PredicateBuilder.False<WorkItem>();

if (cbIdle.Checked)
    predicate = predicate.Or(x => x.Status == Status.Idle);

if (cbProcessing.Checked)
    predicate = predicate.Or(x => x.Status == Status.Processing);

if (cbDone.Checked)
    predicate = predicate.Or(x => x.Status == Status.Done);

workItems.Where(predicate.Compile());

The PredicateBuilder also allows me to nest predicates and create complex conditions. For example, if I wanted to create a predicate that is equivalent to the following:

workItems.Where(x => 
    x.Status == Status.Done &&
    (x.Description.Contains("report") || x.Description.Contains("summary"))
);

… I can create two predicates and append them together.

var description = PredicateBuilder.False<WorkItem>();
description = description.Or(x => x.Description.Contains("report"));
description = description.Or(x => x.Description.Contains("summary"));

var condition = PredicateBuilder.True<WorkItem>();
condition = condition.And(x => x.Status == Status.Done);
condition = condition.And(description);

workItems.Where(condition.Compile());
  1. July 12, 2011 at 5:17 pm

    This is a great post, I think I saw work very similar to that with http://abdullin.com/journal/2009/1/3/strongly-typed-reflection-in-lokad-shared.html

  2. March 17, 2013 at 5:20 pm

    Your weblog is very useful. Thank you so significantly for offering a lot of helpful content. I’ve bookmarked your weblog internet site and are going to be without doubt coming back. When once more, I enjoy all your work and also supplying a great deal crucial tricks for the readers.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: