mrxten / QueryDesigner

QueryDesigner provides way of creating complex IQueryable filtering based on dynamic expression trees.
MIT License
74 stars 26 forks source link

Where filter key sensitive #27

Open mtugnoli opened 4 years ago

mtugnoli commented 4 years ago

In where filters seem is key sensitive.

How resolve this ?

szabolcs-fazakas commented 4 years ago

I have changed the QueryDesigner project. for .AsQueryable()
Solution 1 : use CallTrimToLower() function from below and change the WhereFilterType.StartsWith,Contains,Equals,

... case WhereFilterType.StartsWith: return CallTrimToLower(prop, StartsMethod, filter);

case WhereFilterType.Contains: return CallTrimToLower(prop, ContainsMethod, filter); ... private static readonly MethodInfo Trim = typeof(string).GetMethod("Trim", Type.EmptyTypes); private static readonly MethodInfo ToLower = typeof(string).GetMethod("ToLower", Type.EmptyTypes); private static Expression CallTrimToLower(Expression prop, MethodInfo methodInfo, WhereFilter filter, bool applyToLower = true) { Expression trimMethod = Expression.Call(prop, Trim);
Expression toLowerMethod = applyToLower ? Expression.Call(trimMethod, ToLower) : trimMethod;
Expression target = Expression.Constant(filter.Value.ToString().ToLower(), typeof(string)); //Expression target = Expression.Constant(filter.Value, StringType); Expression method = applyToLower ? Expression.Call(toLowerMethod, methodInfo, target) : Expression.Call(prop, methodInfo, target); return method; } ....

Solution 2 : - probably a better approach as you don't transform the strings. I have created new WhereFilterTypes:

private static readonly MethodInfo EqualsMethod = StringType.GetRuntimeMethod("Equals", new[] { typeof(string), typeof(string), typeof(StringComparison) }); private static readonly MethodInfo StartsMethodStringComparison = StringType.GetRuntimeMethod("StartsWith", new[] { StringType, typeof(StringComparison) }); private static readonly MethodInfo ContainsMethodStringComparison = StringType.GetRuntimeMethod("Contains", new[] { StringType, typeof(StringComparison) }); private static readonly MethodInfo EndsMethodStringComparison = StringType.GetRuntimeMethod("EndsWith", new[] { StringType, typeof(StringComparison) }); ... case WhereFilterType.EqualIgnoreCase: { if (prop.Type == typeof(string)) { return Expression.Call(null, EqualsMethod, new[] { prop, Expression.Constant(filter.Value, typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) }); } else { return Expression.Equal(prop, ToConstantExpressionOfType(TryCastFieldValueType(filter.Value, prop.Type), prop.Type)); } }

case WhereFilterType.NotEqualIgnoreCase: { if (prop.Type == typeof(string)) { return Expression.Not(Expression.Call(null, EqualsMethod, new[] { prop, Expression.Constant(filter.Value, typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) })); } else { return Expression.NotEqual(prop, ToConstantExpressionOfType(TryCastFieldValueType(filter.Value, prop.Type), prop.Type)); } }

case WhereFilterType.StartsWithIgnoreCase: return Expression.Call(prop, StartsMethodStringComparison, Expression.Constant(filter.Value, StringType), Expression.Constant(StringComparison.OrdinalIgnoreCase));

case WhereFilterType.NotStartsWithIgnoreCase: return Expression.Not( Expression.Call(prop, StartsMethodStringComparison, Expression.Constant(filter.Value, StringType), Expression.Constant(StringComparison.OrdinalIgnoreCase)));

case WhereFilterType.ContainsIgnoreCase: return Expression.Call(prop, ContainsMethodStringComparison, Expression.Constant(filter.Value, StringType), Expression.Constant(StringComparison.OrdinalIgnoreCase));

case WhereFilterType.NotContainsIgnoreCase: return Expression.Not( Expression.Call(prop, ContainsMethodStringComparison, Expression.Constant(filter.Value, StringType), Expression.Constant(StringComparison.OrdinalIgnoreCase)));

case WhereFilterType.EndsWithIgnoreCase: return Expression.Call(prop, EndsMethodStringComparison, Expression.Constant(filter.Value, StringType), Expression.Constant(StringComparison.OrdinalIgnoreCase));

case WhereFilterType.NotEndsWithIgnoreCase: return Expression.Not( Expression.Call(prop, EndsMethodStringComparison, Expression.Constant(filter.Value, StringType), Expression.Constant(StringComparison.OrdinalIgnoreCase)));