使用Expression <func <tentity,string =“”>&gt;进行动态查询和EntityFramework

时间:2015-08-11 09:39:32

标签: c# linq entity-framework linq-to-entities

我一直在编写一段代码,允许您在要搜索的实体上定义许多属性。这很简单,但是当你开始使用诸如下面的表达式时,它就会失败:

this.HasColumn(e => e.FirstName + e.LastName, "FullName")

而不只是:

this.HasColumn(e => e.FirstName, "FirstName")

我有一个使用Expression.Call工作的表达式的模型,这是:

BinaryExpression memberExpression = Expression.MakeBinary(ExpressionType.Add, Expression.Property(pe, "FirstName"), Expression.Property(pe, "LastName"));

这是我的代码:

public IQueryable<T> Search(string valueToSearch, IQueryable<T> unfilteredList)
{
    valueToSearch = valueToSearch.Replace(" ", "");

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

    foreach (var propertyName in this.Columns)
    {
        Expression<Func<T, bool>> lambda = null;
        ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "p");

        Expression member = parameterExpression;

        var canConvert = canConvertToType(valueToSearch, member.Type.FullName);

        if (canConvert)
        {
            var value = convertToType(valueToSearch, member.Type.FullName);
            if (IsString)
            {
                ParameterExpression pe = Expression.Parameter(typeof(T), "p");
                var memberExpression = Expression.Add(Expression.Property(pe, "FirstName"), Expression.Property(pe, "LastName"), typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string) }));


                Expression replaceMethodCall = Expression.Call(propertyName.Target, typeof(string).GetMethod("Replace", new[] { typeof(string), typeof(string) }), Expression.Constant(" ", typeof(string)), Expression.Constant("", typeof(string)));

                MethodInfo methodInfo = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
                ConstantExpression constantExpression = Expression.Constant(valueToSearch, typeof(string));

                Expression call = Expression.Call(replaceMethodCall, methodInfo, constantExpression);

                lambda = Expression.Lambda<Func<T, bool>>(call, pe);
            }
            else
            {
                lambda = Expression.Lambda<Func<T, bool>>(Expression.Equal(propertyName.Target.Body, Expression.Constant(value)), parameterExpression);
            }
        }

        if (lambda != null)
        {
            if (expression == null)
            {
                expression = lambda;
            }
            else
            {
                expression = PredicateBuilder.Or(expression, lambda);
            }
        }
    }

    if (expression != null)
    {
        return unfilteredList.Where(expression);
    }

    // return an empty set
    return new List<T>().AsQueryable();
}

我在哪里错了?为什么我只能使用我的Expression<Func<TEntity, string>>作为其中的一部分?

编辑:这一行:

Expression replaceMethodCall = Expression.Call(propertyName.Target, typeof(string).GetMethod("Replace", new[] { typeof(string), typeof(string) }), Expression.Constant(" ", typeof(string)), Expression.Constant("", typeof(string)));

生成此异常:

Additional information: Method 'System.String Replace(System.String, System.String)' declared on type 'System.String' cannot be called with instance of type 'System.Func`2[GlobalSearchTest.Person,System.String]'

0 个答案:

没有答案