tags:

views:

100

answers:

5

Is there anyway to join LINQ where clauses as 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);

What I want is the ability to dynamically add where clauses but make them use OR instead of AND

A: 

Are you talking about specifying more than one condition in the lambda?

query = query.Where(q => q == 3 ||
                         q == 7);
48klocs
But Dynamically
PostMan
A: 

try this

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

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

Pramodh
That's an AND, not an OR.
RPM1984
@ RPM1984 : Thank you ... edited in
Pramodh
It's still not dynamic solution.
MAKKAM
Yep, none of these answers are correct.
RPM1984
+8  A: 

If you want to stay with your strong-typing Linq queries you should look into LinqKit and predicate building. I have used this for something similar and found it to work well with And / Or stacking of filters.

Check out the C#4.0/3.0 in a Nutshell excerpt for more in depth info. Here is a snip from my code:

        //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);
        }
Tj Kellie
yep, sounds like the way to go - or maybe he could use DLINQ?
RPM1984
Interesting solution. Was looking for a way without a separate lib but why reinvent the wheel :)
Vince
even with the linqKit to start with,, don't worry there is still a lot of code to "invent" for your specific solution with this method.
Tj Kellie
+1  A: 

How about something like this?

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

You can probably expand this to be a bit cleverer but that's sort of how I'd do it.

EDIT: Sorry the first example was an AND, have changed it now to be an OR. So the first time it encounters a passing condition it returns true.

Darko Z
+1 I was just about to type something similar
MAKKAM
+2  A: 

Using ExpressionVisitor to help to build the expression base on two expressions with OR/AND relationship. This answer is from 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);
}
Danny Chen