skip to Main Content

I struggle with adding ToLower() to the Contains LINQ Expressions:
Here is the code of mine with dynamic LINQ Expressions (Contains):

private static Expression GetExpressionCase<T>(ParameterExpression param, SearchCriteria searchCriteria)
{
    MethodInfo containsMethod =
        typeof(string).GetMethod("Contains", new[] { typeof(string) });

    MemberExpression member =
        Expression.Property(param, searchCriteria.Key);

    ConstantExpression constant =
        Expression.Constant(Convert.ChangeType(searchCriteria.Value, member.Type));

    switch (searchCriteria.Operation)
    {
        case '=':
            return Expression.Equal(member, constant);

        case '>':
            return Expression.GreaterThanOrEqual(member, constant);

        case '<':
            return Expression.LessThanOrEqual(member, constant);

        case ':':
            return Expression.Call(member, containsMethod, constant);
     }

     return null;
}

My codes works fine but i want to add ToLower() before Contains() like this query:

Current query looks likes this (Contains() only):

var test = context.Table.Where(x => x.Key.Contains("value"));

I hope query will look likes this (Added ToLower()):

var test = context.Table.Where(x => x.Key.ToLower().Contains("hoa"));

I’ve already tried using StringComparison.OrdinalIgnoreCase but it can’t be translated by the query provider (postgreSQL).

3

Answers


  1. fi => fi.DESCRIPTION.ToLower().Contains(description.ToLower())
    
    Login or Signup to reply.
  2. You’re doing it well, I only would suggest simply chaining the result of the ToLower call with Contains.

    case ':':
        MethodInfo containsMethod =
            typeof(string).GetMethod(nameof(string.Contains), new[] { typeof(string) });
    
        MethodInfo toLowerMethod =
            typeof(string).GetMethod(nameof(string.ToLower), Type.EmptyTypes);
    
        MethodCallExpression toLowerCall = // X.ToLower();
            Expression.Call(member, toLowerMethod, constant);
    
        MethodCallExpression containsCall = // X.Contains(Y);
            Expression.Call(toLowerCall, containsMethod, constant);
    
        return containsCall;
    
    Login or Signup to reply.
  3. Try the following realisation. I have simplified it a little bit.

    private static Expression? GetExpressionCase(ParameterExpression param, SearchCriteria searchCriteria, bool makeLower)
    {
        Expression memberExpression = Expression.Property(param, searchCriteria.Key);
    
        if (makeLower && memberExpression.Type == typeof(string))
        {
            memberExpression = Expression.Call(memberExpression, nameof(string.ToLower), Type.EmptyTypes, memberExpression);
        }
    
        var searchValue = searchCriteria.Value;
        if (makeLower && searchValue is string str)
        {
            searchValue = str.ToLower();
        }
    
        var constant = Expression.Constant(Convert.ChangeType(searchValue, memberExpression.Type));
    
        switch (searchCriteria.Operation)
        {
            case '=':
                return Expression.Equal(memberExpression, constant);
    
            case '>':
                return Expression.GreaterThanOrEqual(memberExpression, constant);
    
            case '<':
                return Expression.LessThanOrEqual(memberExpression, constant);
    
            case ':':
                return Expression.Call(memberExpression, nameof(string.Contains), Type.EmptyTypes, constant);
    
            default:
                return null;
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search