How to create a dynamic 'contains or LIKE' Expression to be used with Linq against OData service

c# expression-trees linq odata

Question

I'm try'n to create a dynamic query tool using System.Linq.Expressions.Expression (WPF/c#4.0) It runs against an OData Service.

So far, all is working as long as I limit the conditions to build in options like Equal(..), GreaterThan(..) etc. There seems to be no build in contains/Like condition so I tried building my own. There are a handful of articles already out there. One I tried is How to create a System.Linq.Expressions.Expression for Like?.

Now if I use the above solution, the resulting where expression is

whereCallExpression = {Convert([10000]).Expand("A,B").Where(clt => MyLike(clt.LastName, "te"))}'

which is nice, but wrong, since it does not translate into a valid Odata query.

If I use condition 'Equal', the result is

whereCallExpression = {Convert([10000]).Expand("A,B").Where(clt => (clt.LastName == "te"))}

which results in the OData query

results = {http://.../Clients()?$filter=LastName eq 'te'&$expand=A,B} 

and is working as expected.

Am I doing something wrong with the implementation of the solution, or can it not be used with OData?

It should transfer to something like ...?$filter=substringof('te', LastName ) eq true

Any solution on how to fix this?

Regards

Andreas

PS, I implemented the solution extension in a static class, all I changed is the name of the called method from 'Like' to 'MyLike' Also, since the code used to build the expressions is working with any of the build-in condition, I assume, for now that part is ok. I can post parts of it if needed

Accepted Answer

OData currently doesn't support the "like" operator at all. So no matter what you do on the client, the URL produced has not way of expressing that. The substringof is supported and the client LINQ provider should generate it when you use string.Contains method in your filter (Where) expression.

To get the expression generated by a C# compiler you can do something like this:

IQueryable<string> source = new List<string>().AsQueryable();
IQueryable<string> result = from item in source where item.Contains("John") select item;
Console.WriteLine(result.Expression.ToString());

Basically any IQueryable has a property Expression which contains the expression tree for the query to run. Some LINQ providers might change the expression tree somewhat from the original one created by the compiler, but most should leave it close to the original.




Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why