Объединение нескольких предложений 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 )
                    );