Using the LIKE operator in Dynamic LINQ

521 Views Asked by At

Note: If you have the same problem and found this question before the "duplicated" one, be aware that the answer to that question does not work. I marked the only working solution below.

I'm trying to follow this guide which states that this should be possible in Dynamic LINQ:

var config = new ParsingConfig { ResolveTypesBySimpleName = true };
var example2 = Cars.Where(config, "DynamicFunctions.Like(Brand, \"%t%\")");
example2.Dump();

I'm using string concatination to build a complex query:

IQueryable<DtcViewEntity> queryable = ...
string[] values = { "%a%" };
string myOperator = "and"; // or sometimes "or"
bool isNot = false; // or sometimes "true"

var query = string.Join($" {myOperator} ", values.Select((value, index) => $"DynamicFunctions.Like(MyColumn, @{index})"));
if (isNot)  query = $"not ({query})";
var config = new ParsingConfig { ResolveTypesBySimpleName = true };
return queryable.Where(config, query, values);

But the actual error can be reproduced with code that looks almost identical to the example in the guide:

IQueryable<DtcViewEntity> queryable = ...

var config = new ParsingConfig { ResolveTypesBySimpleName = true };
var result = queryable.Where(config,  "DynamicFunctions.Like(MyColumn, \"%a%\")").ToList();

And I get:

System.Linq.Dynamic.Core.Exceptions.ParseException : Enum type 'DynamicFunctions' not found
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAsEnum(String id)
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseMemberAccess(Type type, Expression expression)
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIdentifier()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParsePrimaryStart()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParsePrimary()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseUnary()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseMultiplicative()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAdditive()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseShiftOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseComparisonOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLogicalAndOrOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIn()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAndOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseOrOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLambdaOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseNullCoalescingOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseConditionalOperator()

I've seen this code as well, but using var config = ParsingConfig.DefaultEFCore21; will result in

System.Linq.Dynamic.Core.Exceptions.ParseException : Enum type 'DynamicFunctions' not found
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAsEnum(String id)
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseMemberAccess(Type type, Expression expression)
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIdentifier()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParsePrimaryStart()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParsePrimary()

After adding Microsoft.EntityFrameworkCore.DynamicLinq to the dependencies I get:

System.Linq.Dynamic.Core.Exceptions.ParseException : No applicable method 'Like' exists in type 'DynamicFunctions'

Falco Alexander even found a "working example" form ZZZ Projects that produces the very same error message:

Unhandled exception. Enum type 'DynamicFunctions' not found (at index 21)
Command terminated by signal 6

I can't find any information on this exception, so my question is: what am I doing wrong?

3

There are 3 best solutions below

0
Svyatoslav Danyliv On BEST ANSWER

Get Extension methods from this answer. It contains GetItemsPredicate function, which will help in building predicate.

Then we can generate needed predicate without Dynamic.Linq and avoid raw text parsing.


// input parameters
string[] values = { "%a%" };
var isOr = true;
var isNot = false;

var predicate = queryable.GetItemsPredicate(values, (e, v) => EF.Functions.Like(e.MyColumn, v), isOr);

if (isNot)
{
    // inversion
    predicate = Expression.Lambda<Func<DtcViewEntity, bool>>(Expression.Not(predicate.Body), predicate.Parameters);
}

// applying generated predicate
queryable = queryable.Where(predicate);
1
G.Medina On

Looks like the errors you are getting have to do with Linq not being able to "transform" the data so it can parse it or something along those lines Is it possible for you instead of the "Like" operator you use the "Contains"?

var Something = SomethingElse.Filter(x => x.Argument.Contains(Description));
0
Falco Alexander On

my code runs fine if I use EF.Functions directly

var result = context.Cars.Where(c => EF.Functions.Like(c.Brand, "%a%")).ToList();

also testing with Linqpad and Northwind localDB with a different non-EF provider.

var config = new ParsingConfig { ResolveTypesBySimpleName = true };
var example2 =  from c in Customers
                where SqlMethods.Like(c.City, "[aeiou]%")
                select c;