Объединение нескольких предложений where в LINQ как OR вместо AND
В любом случае, чтобы присоединиться к LINQ где предложения как OR?
var ints = new [] { 1, 3, 5, 7 };
var query = from i in ints select i;
query = query.Where (q => q == 3);
query = query..Where (q => q == 7);
То, что я хочу, - это возможность динамически добавлять предложения where, но заставить их использовать OR вместо AND
Ответы
Ответ 1
Если вы хотите остаться с вашими типичными запросами Linq, вы должны изучить LinqKit и предикат. Я использовал это для чего-то подобного и нашел, что он хорошо работает с And/or stacking of filters.
Ознакомьтесь с С# 4.0/3.0 в выдержке из ореховой скорлупы для более подробной информации. Вот отрезок моего кода:
//Setup the initial predicate obj then stack on others:
basePredicate = basePredicate.And(p => false);
var predicate1 = PredicateBuilder.True<Person>();
foreach (SearchParms parm in parms)
{
switch (parm.field)
{
case "firstname":
predicate1 = predicate1.And(p => p.FirstName.Trim().ToLower().Contains(sValue));
break;
//etc...
}
}
//Run a switch based on your and/or parm value to determine stacking:
if (Parm.isAnd) {
basePredicate = basePredicate.And(predicate1);
} else {
basePredicate = basePredicate.Or(predicate1);
}
Ответ 2
Как насчет чего-то подобного?
var query = from i in ints where CheckConditions(i) select i;
public bool CheckConditions(int i)
{
var conditions = WhereConditions; //an IEnumerable<Func<int, bool>> of dynamically added conditions
foreach (var condition in conditions)
{
if (condition(i)) return true;
}
return false;
}
Возможно, вы можете расширить это, чтобы быть немного умнее, но как бы я это сделал.
РЕДАКТИРОВАТЬ: Извините, что первым примером был И, изменили его теперь как OR. Поэтому при первом запуске условия передачи он возвращает true.
Ответ 3
Использование ExpressionVisitor
, чтобы помочь построить базу выражений на двух выражениях с отношением OR/AND. Этот ответ из Jeffery Zhao blog.
internal class ParameterReplacer : ExpressionVisitor
{
public ParameterReplacer(ParameterExpression paramExpr)
{
this.ParameterExpression = paramExpr;
}
public ParameterExpression ParameterExpression { get; private set; }
public Expression Replace(Expression expr)
{
return this.Visit(expr);
}
protected override Expression VisitParameter(ParameterExpression p)
{
return this.ParameterExpression;
}
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> one, Expression<Func<T, bool>> another)
{
var candidateExpr = Expression.Parameter(typeof(T), "candidate");
var parameterReplacer = new ParameterReplacer(candidateExpr);
var left = parameterReplacer.Replace(one.Body);
var right = parameterReplacer.Replace(another.Body);
var body = Expression.And(left, right);
return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> one, Expression<Func<T, bool>> another)
{
var candidateExpr = Expression.Parameter(typeof(T), "candidate");
var parameterReplacer = new ParameterReplacer(candidateExpr);
var left = parameterReplacer.Replace(one.Body);
var right = parameterReplacer.Replace(another.Body);
var body = Expression.Or(left, right);
return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
}
Ответ 4
Вы можете использовать метод Union:
var ints = new [] { 1, 3, 5, 7 };
var query = ints.Where(q => q == 3);
query = query.Union(ints.Where(q => q == 7));
Ответ 5
Вы говорите о том, чтобы указать более одного условия в лямбда?
query = query.Where(q => q == 3 ||
q == 7);
Ответ 6
попробуйте это
var ints = new [] { 1, 3, 5, 7 };
var query = ints.select(X=>X).where(X=>X==3||X==7);
Ответ 7
Я пытаюсь сделать что-то подобное. Вот что я придумал:
//various test cases
bool useTestCase1 = true;
bool useTestCase2 = true;
bool useTestCase3 = false;
query = query.Where(q =>
(q == 3 && useTestCase1 ) ||
(q == 7 && useTestCase2 ) ||
(q == 10 && useTestCase3 )
);