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:
Entity Framework is able to convert this expression into a SQL “where” condition.
Nothing new… But I think this is not widely used.