Entity Framework and Expression Queries

By | July 16, 2014

In my current project I had to generate a Entity Framework query based on some search criterias defined in a dictionary.
The structure of the dictionary was similar to this example here:

var searchCriteria = new Dictionary<string, List<string>>() 
{
    { "FirstName", new List<string> { "Darko", "NoName" } },
    { "LastName", new List<string> { "Micic", "Müller", "Obama" } }
};

The key contained the property/column name and the value containted a list of search criterias for this column. So first I wanted to build the query the type-safe way:

var query = model.People.AsQueryable();

if (searchCriteria.ContainsKey("FirstName"))
{
    var firstNames = searchCriteria["FirstName"];
    query = query.Where(x => firstNames.Contains(x.FirstName));
}

var result = query.ToList();

But I didn’t like that approach, because I need to handle each possible property on its own.
Therefore I decided to generate the query based on expressions. This is not a type-safe solution, but the approach leads to less code 🙂

BinaryExpression condition = null;
var parameter = Expression.Parameter(typeof(Person), "p");

foreach (var criteria in searchCriteria)
{
    foreach (var comparisonValue in criteria.Value)
    {
        var property = Expression.Property(parameter, criteria.Key);
        var equalityCheck = Expression.Equal(property, Expression.Constant(comparisonValue));
        condition = condition == null ? equalityCheck : Expression.Or(condition, equalityCheck);
    }
}

The “condition” variable is an expression tree which contains “OR” combined comparison checks based on the search criteria. This expression can be used this way:

var query = model.People;
var predicate = Expression.Lambda<Func<Person, bool>>(condition, parameter);
var result = query.Where(predicate).ToList();

In debug mode we see how the comparison checks ar stitched together:
Ef Expression Condition
Entity Framework is able to convert this expression into a SQL “where” condition.

Nothing new… But I think this is not widely used.