表达式树,多个字符串。包含谓词,无法翻译

时间:2020-08-04 22:52:18

标签: c# expression-trees

我正在尝试建立一个动态搜索,该搜索在一组特定的属性中查找字符串。 对单个属性执行此操作没有任何问题,但是当我添加多个属性时,它将引发以下错误:

InvalidOperationException:LINQ表达式' DbSet <Person> .Where(a => a.Id.ToString()。Contains(“ test”)|| a.Name.ToString()。Contains(“ test”))

无法翻译。** 可以以可翻译的形式重写查询,也可以通过插入对AsEnumerable(),AsAsyncEnumerable(),ToList()或ToListAsync()的调用来显式切换到客户端评估。

    public class Person {
     public string Name {get; set;}
     public int Id {get; set;}
    }   

    private static Expression GetMemberExpression(ParameterExpression parameter, string propertyName)
    {
        Expression body = parameter;
        foreach (var member in propertyName.Split('.'))
        {
            body = Expression.PropertyOrField(body, member);
        }
        return body;
    }


    public static IQueryable<T> Search<T>(this IQueryable<T> source, string searchCriteria, string searchQuery)
    {
        if (string.IsNullOrWhiteSpace(searchQuery) || string.IsNullOrWhiteSpace(searchCriteria))
        {
            return source;
        }

        ParameterExpression parameter = Expression.Parameter(source.ElementType);
        List<Expression> expTree = new List<Expression>();

        foreach (var propertyName in searchCriteria.Split(","))
        {
            Expression memberExpression = GetMemberExpression(parameter, propertyName);

            MethodCallExpression toStringExpression = Expression.Call(memberExpression, typeof(object).GetMethod("ToString"));

            ConstantExpression constantExpression = Expression.Constant(searchQuery.ToLower(), typeof(string));

            MethodCallExpression containsExpression = Expression.Call(toStringExpression, typeof(string)
                .GetMethod("Contains", new[] { typeof(string) }), constantExpression);

            expTree.Add(containsExpression);
        }

        Expression body = expTree
            .Skip(1)
            .Aggregate(expTree.FirstOrDefault(),
                (current, exp) => Expression.OrElse(current, exp));

        var lambda = Expression.Lambda(body, parameter);

        Expression whereCallExpression = Expression.Call(typeof(Queryable),
            "Where",
            new Type[] { source.ElementType },
            source.Expression, lambda);

        return source.Provider.CreateQuery<T>(whereCallExpression);
    }

public async Task Test() {
  await dbContext.People.Search("Name","test").ToListAsync(); // this is fine
  await dbContext.People.Search("Id,Name","test").ToListAsync(); // Throws an exception

}

0 个答案:

没有答案