Share via


Writing a Very Basic Dynamic Query using Expression Trees

In this wiki, let’s see how we can write a very simple query using expression trees which gets generated at the run time. If you are not aware of Expression Trees, let me quickly give you an introduction.

Expression trees represent code in a tree-like data structure, where each node is an expression. The nicest thing about expression trees is, in the run time you can compile and run the code represented by expression trees. Because of this nature you can do many things. One example would be dynamic queries, which means based on your conditions defined in the code, you can create your query in the run time.

This is the query which I am going to construct with expression trees.

employees.Where(e => e.Country == "Sri Lanka");

Pretty simple right? Yes it is a very basic query, the reason for me to use this query as the model is because the more simpler the query, I will need to have a simple expression. But I believe, that simple expression tree is more than enough to get you start writing complex expression trees.

So Let’s get into action. I have following simple model which is “Employee”.

public class Employee
{
    public int EmployeeId { get; set; }
    public string Name { get; set; }
    public string Country { get; set; }
 
    public static List<Employee> GetEmployees()
    {
        return new List<Employee>()
        {
            new Employee(){EmployeeId=1,Name="Jaliya Udagedara", Country="Sri Lanka"},
            new Employee(){EmployeeId=2,Name="John Smith", Country="United States"},
            new Employee(){EmployeeId=3,Name="Jane Smith", Country="United States"},
        };
    }
}

I don’t think I need to explain every line of code up there. In my Main method, I have the following code.

static void Main(string[] args)
{
    List<Employee> employees = Employee.GetEmployees();
    var filteredEmployees = employees.Where(e => e.Country == "Sri Lanka");
    foreach (var item in filteredEmployees)
    {
        Console.WriteLine(item.Name);
    }
}

Here Where extension method expects a Func<Employee,bool> predicate.

http://lh4.ggpht.com/-xQkap635kxE/U6vnx3KRuCI/AAAAAAAACcQ/zgdCZz7eC24/image_thumb%25255B8%25255D.png?imgmax=800
Func<Employee,bool> predicate

If you are wondering what Func is, read this wiki which explains Action, Func<TResult> and Predicate<T> Delegate.

So if I run this, I am getting the expected output, and that’s of course no magic.

http://lh6.ggpht.com/-yGGELqCFUZY/U6vnzuJobVI/AAAAAAAACcg/ijk_VWqfpiE/image_thumb%25255B3%25255D.png?imgmax=800
Output

Now let’s see how we can write expression tree which generates the same query.

First step is to create the expression tree that represents the parameter to the predicate which is “e”.

ParameterExpression pe = Expression.Parameter(typeof(Employee), "e");

As you know every expression has two sides, left and right. And in the middle there will be an operator. Now let’s write the expression which points to the left side of the expression.

Expression left = Expression.Property(pe, typeof(Employee).GetProperty("Country"));

Now above two expressions are responsible for composing the following.

e=>e.Country

Let’s move into the right side of the expression. In the right hand side, I have a value.

Expression right = Expression.Constant("Sri Lanka");

Now what we need to do is perform some operation on these left and right expressions. Here what we need is the equality operator (==).

Expression expression = Expression.Equal(left, right);

Ok, now all done. Final step is, compile the expression tree into executable code.

var lambda = Expression.Lambda<Func<Employee, bool>>(expression, pe).Compile();

The compiled lambda expression is as follows.

e => e.Country == "Sri Lanka"

Now I can pass the compiled lambda expression to Where extension method.

var filteredEmployees = employees.Where(lambda);

That’s all. So following is how it looks like when all above parts come together.

ParameterExpression pe = Expression.Parameter(typeof(Employee), "e");
Expression left = Expression.Property(pe, typeof(Employee).GetProperty("Country"));
Expression right = Expression.Constant("Sri Lanka");
Expression expression = Expression.Equal(left, right);
var lambda = Expression.Lambda<Func<Employee, bool>>(expression, pe).Compile();
var filteredEmployees = employees.Where(lambda);

And this is the output when I foreach on “filteredEmployees”.

http://lh6.ggpht.com/-ABl9CCt8NpU/U6vn1RnFTTI/AAAAAAAACcw/ZA-BiTeKZwc/image_thumb%25255B11%25255D.png?imgmax=800
Output

I am uploading the full sample to MSDN Code Gallery. Enjoy!
   Download Sample

Happy Coding.


See Also