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