Я пытаюсь создать динамический c поиск, который ищет строку в определенном c наборе свойств. Нет никаких проблем в том, чтобы сделать это для одного свойства, но когда я добавляю более одного, возникает следующая ошибка:
InvalidOperationException: выражение LINQ 'DbSet <Person>
.Where (a => a.Id.ToString (). Contains ("test") || a.Name.ToString (). Contains ("test"))
не может быть переведено. ** Перепишите запрос в форме, которая может быть переведена, или явно переключиться на оценку клиента, вставив вызов в AsEnumerable (), AsAsyncEnumerable (), ToList () или ToListAsyn c ().
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
}