linq到实体的不区分大小写的动态搜索

时间:2011-09-15 21:11:43

标签: .net linq

对于question,答案表明我们不能将LINQ to SQL或linq用于实体。

如果我写

Expression toLower = Expression.Call(memberAccess, typeof(T).GetMethod("IndexOf",
                                     new[] { typeof(T), typeof(StringComparison) }));
  Expression  condition = Expression.Call(toLower,
                                typeof(string).GetMethod("Contains"),
                                Expression.Constant(value.ToString().ToLower()));
                    lambda = Expression.Lambda(condition, parameter);

我收到错误:

Value cannot be null. Parameter name: method

如果我写

Expression toLower = Expression.Call(memberAccess, typeof(string).GetMethod("IndexOf",
                                         new[] { typeof(string), typeof(StringComparison) }));

我得到的错误是:

Incorrect number of arguments supplied for call to method 'Int32 IndexOf(System.String, System.StringComparison)'

提前致谢

修改 这是片段,我需要能够做一个不区分大小写的过滤器:

public static IQueryable<T> Where<T>(this IQueryable<T> query,
            string column, object value, WhereOperation operation)
        {
            if (string.IsNullOrEmpty(column))
                return query;

            ParameterExpression parameter = Expression.Parameter(query.ElementType, "p");

            MemberExpression memberAccess = null;
            foreach (var property in column.Split('.'))
                memberAccess = MemberExpression.Property
                   (memberAccess ?? (parameter as Expression), property);

            //change param value type
            //necessary to getting bool from string
            ConstantExpression filter = Expression.Constant
                (
                    Convert.ChangeType(value, memberAccess.Type)
                );

            //switch operation
            Expression condition = null;
            LambdaExpression lambda = null;
            switch (operation)
            {
                //equal ==
                case WhereOperation.Equal:
                    condition = Expression.Equal(memberAccess, filter);
                    lambda = Expression.Lambda(condition, parameter);
                    break;
                //not equal !=
                case WhereOperation.NotEqual:
                    condition = Expression.NotEqual(memberAccess, filter);
                    lambda = Expression.Lambda(condition, parameter);
                    break;
                //string.Contains()
                case WhereOperation.Contains:
                    condition = Expression.Call(memberAccess,
                        typeof(string).GetMethod("Contains"),
                        Expression.Constant(value));
                    lambda = Expression.Lambda(condition, parameter);
                    break;
            }


            MethodCallExpression result = Expression.Call(
                   typeof(Queryable), "Where",
                   new[] { query.ElementType },
                   query.Expression,
                   lambda);

            return query.Provider.CreateQuery<T>(result);
        }

2 个答案:

答案 0 :(得分:3)

将代码修改为:

   Expression  toLower = Expression.Call(memberAccess, "ToLower", null, null);                  
   lambda = Expression.Lambda(condition, parameter);

答案 1 :(得分:2)

您试图在不指定任何参数的情况下调用IndexOf。然后你试图将结果用作Contains调用的目标,这有点奇怪......我怀疑你真的想要:

Expression indexOf = Expression.Call(memberAccess, "IndexOf", null,
                        Expression.Constant(value.ToString()),
                        Expression.Constant(StringComparison.OrdinalIgnoreCase));

Expression condition = Expression.NotEqual(indexOf, Expression.Constant(-1));

lambda = Expression.Lambda(condition, parameter);

如果您可以向我们提供有关您正在尝试实现的内容的更多信息 - 最好是使用简短但完整的程序 - 这将更容易为您提供帮助。

编辑:以编译时安全的方式使用Where更有意义,如下所示:

Expression<Func<T, bool>> lambda = null;

...

lambda = Expression.Lambda<Func<T, bool>>(condition, parameter);
return query.Where(lambda);