I recently stumpled upon the problem to dynamically create Linq expressions during runtime. Most examples I found deal with the rather simple task of just comparing one property of a given database entity with a single parameter. Like so:
Session.Query.Where(m => m.Name.Contains("test"))
Which could also be achieved with a far more generic approach like this:
var item = Expression.Parameter(typeof (MyClass), "item");
var property = Expression.Property(item, "Name");
var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var searchExpression = Expression.Constant(searchString, typeof(string));
var containsMethodExpression = Expression.Call(property, containsMethod, searchExpression);
var lambda = Expression.Lambda<Func<MyClass, bool>>(containsMethodExpression, item);
query = query.Where(lambda);
However, sometimes the task is somewhat more complex and one wants to attain something like the following:
Session.Query.Where(m => m.SpecialProperty.Any(f => f.Name.Contains("test")));
Where "SpecialProperty" is of the type List<> and the property "Name" is of the type string.
Is it possible to build a Linq expression like this dynamically and how could this be achieved? Are there any performance concerns regarding this approach?
The examples below are all related to this repository. SQL Server and .NET Core power the application and it contains three examples of building a dynamic query using LINQ expressions.
The query will contain a Where clause and we will create a dynamic Lambda expression in the Where clause. If you open a class on any .NET project, and import the library "System.Linq.Expressions", you can call the class "Expression" and there are a large number of static methods within this class.
LINQ expressions are a very powerful tool to filter and transform data. I hope this example helped demystify how expression trees are built. Of course, parsing the expression tree feels a little like magic.
There is a way around this and it comes in the form of LINQ expressions. You can keep on building up each part of the LINQ expression bit by bit. And when you are happy, you can convert it into a Lambda expression ready to be used in Entity Framework.
Found a solution that is working in my particular use case and does exactly what I was looking for.
/*
building expression tree
example: Session.Query.Where(m => m.SpecialProperty.Any(f => f.Name.Contains("test")))
*/
var innerItem = Expression.Parameter(typeof(MyInnerClass), "f");
var innerProperty = Expression.Property(innerItem, "Name");
var innerMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var innerSearchExpression = Expression.Constant(searchString, typeof(string));
var innerMethodExpression = Expression.Call(innerProperty, innerMethod, new[] { innerSearchExpression });
var innerLambda = Expression.Lambda<Func<MyInnerClass, bool>>(innerMethodExpression, innerItem);
var outerItem = Expression.Parameter(typeof(MyOuterClass), "m");
var outerProperty = Expression.Property(outerItem, info.Name);
/* calling a method extension defined in Enumerable */
var outerMethodExpression = Expression.Call(typeof(Enumerable), "Any", new[] { typeof(MyInnerClass) }, outerProperty, innerLambda);
var outerLambda = Expression.Lambda<Func<MyOuterClass, bool>>(outerMethodExpression, outerItem);
query = query.Where(outerLambda);
This rather dowdy approach is needed instead of the more elegant single line LINQ-Expression to allow for parametrization of types and method names. However, I of course wouldn't mind other suggestions and ideas on possible performance penalties.
It is very likely that this code snippet could also assist in solving How to produce a Subquery using non-generic Lambda.
I recommend you look at these links:
Joseph and Ben Albahari's PredicateBuilder
The LINQ dynamic query library
I haven't used either for a while, but one or the other should help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With