Хотя вы можете создать метод-обертку для объединения набора Func
s, поскольку вы используете Entity Framework, это приведет к загрузке всего набора данных в память и выполнению локального поиска. Вместо этого вам следует использовать Expression<Func<T, bool>>
.
К счастью Марк Гравелл уже написал небольшой фрагмент кода для объединения выражений . Ваш вопрос является строго дублирующим, потому что вы хотите объединить более двух вместе, но это довольно просто с небольшим Linq. Итак, давайте сначала начнем с ваших выражений, код почти не меняется:
var expressions = new List<Expression<Func<User, bool>>>()
{
(u) => u.Id.Equals(entityToFind.Id),
(u) => u.UserName == entityToFind.UserName,
(u) => u.Email == entityToFind.Email
};
Теперь используя код Марка и изменив его на or
вместо and
:
public static class ExpressionExtensions
{
public static Expression<Func<T, bool>> OrElse<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var parameter = Expression.Parameter(typeof(T));
var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
var left = leftVisitor.Visit(expr1.Body);
var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
var right = rightVisitor.Visit(expr2.Body);
return Expression.Lambda<Func<T, bool>>(
Expression.OrElse(left, right), parameter);
}
private class ReplaceExpressionVisitor
: ExpressionVisitor
{
private readonly Expression _oldValue;
private readonly Expression _newValue;
public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
{
_oldValue = oldValue;
_newValue = newValue;
}
public override Expression Visit(Expression node)
{
if (node == _oldValue)
return _newValue;
return base.Visit(node);
}
}
}
Нет, вы комбинируете выражения с методом Linq Aggregate
:
var combinedExpression = expressions.Aggregate((x, y) => x.OrElse(y));
И используйте что-то вроде этого:
var result = db.Things.Where(combinedExpression);