У меня есть форма с несколькими полями на нем (название компании, почтовый индекс, и т.д.), который позволяет пользователю искать компании в базе данных. Если пользователь вводит значения больше чем в одно поле тогда, я должен искать на всех тех полях. Я использую LINQ для запросов базы данных.
До сих пор мне удалось записать функцию, которая посмотрит на их вход и превратит его в Список выражений. Я теперь хочу превратить тот Список в отдельное выражение, которое я могу тогда выполнить через поставщика LINQ.
Моя начальная попытка была следующие
private Expression<Func<Company, bool>> Combine(IList<Expression<Func<Company, bool>>> expressions)
{
if (expressions.Count == 0)
{
return null;
}
if (expressions.Count == 1)
{
return expressions[0];
}
Expression<Func<Company, bool>> combined = expressions[0];
expressions.Skip(1).ToList().ForEach(expr => combined = Expression.And(combined, expr));
return combined;
}
Однако это перестало работать с сообщением об исключении вроде "Бинарного оператора И не определяется для...". У кого-либо есть какие-либо идеи, что я должен сделать для объединения этих выражений?
Править: Исправленный строка, где я забыл присваивать результат and'ing выражения вместе к переменной. Спасибо за указание на это люди.
РЕДАКТИРОВАТЬ: ответ Джейсона теперь более полный, чем мой, с точки зрения материала дерева выражений, поэтому Я удалил этот бит. Однако я хотел оставить это:
Я полагаю, вы используете их для предложения Where
... почему бы просто не вызвать Where с каждым выражением по очереди? Это должно иметь тот же эффект:
var query = ...;
foreach (var condition in conditions)
{
query = query.Where(condition);
}
Вы можете использовать Enumerable.Aggregate
] в сочетании с Expression.Also
. Вот общая версия:
Expression<Func<T, bool>> AndAll<T>(
IEnumerable<Expression<Func<T, bool>>> expressions) {
if(expressions == null) {
throw new ArgumentNullException("expressions");
}
if(expressions.Count() == 0) {
return t => true;
}
Type delegateType = typeof(Func<,>)
.GetGenericTypeDefinition()
.MakeGenericType(new[] {
typeof(T),
typeof(bool)
}
);
var combined = expressions
.Cast<Expression>()
.Aggregate((e1, e2) => Expression.AndAlso(e1, e2));
return (Expression<Func<T,bool>>)Expression.Lambda(delegateType, combined);
}
Ваш текущий код никогда не присваивается вместе
:
expr => Expression.And(combined, expr);
возвращает новое выражение
, которое является результатом побитового anding вместе
и expr
, но он не мутирует в сочетании
.