Home > database >  Using the LIKE operator in Dynamic LINQ
Using the LIKE operator in Dynamic LINQ

Time:11-02

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'

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

CodePudding user response:

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));

CodePudding user response:

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);

CodePudding user response:

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;
  • Related