将LINQ中的多个where子句连接为OR而不是AND

时间:2010-09-28 03:48:10

标签: c# linq

无论如何加入LINQ where子句为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

7 个答案:

答案 0 :(得分:14)

如果您想继续使用强类型Linq查询,您应该查看LinqKit和谓词构建。我已经将它用于类似的东西,并发现它与And / Or堆叠过滤器一起使用。

查看C#4.0/3.0 in a Nutshell excerpt以获取更多深度信息。以下是我的代码片段:

        //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);
        }

答案 1 :(得分: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;
}

你可以扩展这个有点聪明,但这就是我的方式。

编辑:抱歉,第一个例子是AND,现在已将其更改为OR。所以第一次遇到传递条件时它返回true。

答案 2 :(得分:2)

使用ExpressionVisitor帮助构建基于具有OR / AND关系的两个表达式的表达式。这个答案来自Jeffery Zhao's 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);
}

答案 3 :(得分:0)

您可以使用Union方法:

import acm.program.*;
public class Morse extends Program{
public void run(){
    println("Hello, please enter the text that you want to convert to Morse.");
    String txt = readLine();
    txt = txt.toUpperCase();
    for(int j = 0;j <= txt.length()-1;j++){
        int i;
        for (i=0;i<=26;i++){ //alphabet[26] is a white space
            if (alphabet[i]==txt.charAt(j)){
                if (txt.charAt(j)==' '){
                    System.out.print(System.lineSeparator());
                }else{
                    System.out.print(" " + code[i] + " ");
                }
            }
        }
    }
}
private final String[] code = { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.","--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-","-.--", "--..","\n"};
private final char[] alphabet = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',' '};
}

答案 4 :(得分:-2)

你是在谈论在lambda中指定多个条件吗?

query = query.Where(q => q == 3 ||
                         q == 7);

答案 5 :(得分:-3)

试试这个

var ints = new [] { 1, 3, 5, 7 };

var query = ints.select(X=>X).where(X=>X==3||X==7);

答案 6 :(得分:-3)

我正在尝试做类似的事情。这就是我想出的:

//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 )
                    );