I have a LINQ query that looks like the following:
DateTime today = DateTime.UtcNow;
var results = from order in context.Orders
where ((order.OrderDate <= today) && (today <= order.OrderDate))
select order;
I am trying to learn / understand LINQ. In some cases, I need to add two additional WHERE clauses. In an effort to do this, I'm using:
if (useAdditionalClauses)
{
results = results.Where(o => o.OrderStatus == OrderStatus.Open) // Now I'm stuck.
}
As you can see, I know how to add an additional WHERE clause. But how do I add multiple? For instance, I'd like to add
WHERE o.OrderStatus == OrderStatus.Open AND o.CustomerID == customerID
to my previous query. How do I do this using extension methods?
Thank you!
Just use the &&
operator like you would with any other statement that you need to do boolean logic.
if (useAdditionalClauses)
{
results = results.Where(
o => o.OrderStatus == OrderStatus.Open
&& o.CustomerID == customerID)
}
results = context.Orders.Where(o => o.OrderDate <= today && today <= o.OrderDate)
The select is uneeded as you are already working with an order.
you can use && and write all conditions in to the same where clause, or you can .Where().Where().Where()... and so on.
If you working with in-memory data (read "collections of POCO") you may also stack your expressions together using PredicateBuilder like so:
// initial "false" condition just to start "OR" clause with
var predicate = PredicateBuilder.False<YourDataClass>();
if (condition1)
{
predicate = predicate.Or(d => d.SomeStringProperty == "Tom");
}
if (condition2)
{
predicate = predicate.Or(d => d.SomeStringProperty == "Alex");
}
if (condition3)
{
predicate = predicate.And(d => d.SomeIntProperty >= 4);
}
return originalCollection.Where<YourDataClass>(predicate.Compile());
The full source of mentioned PredicateBuilder
is bellow (but you could also check the original page with a few more examples):
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T> () { return f => true; }
public static Expression<Func<T, bool>> False<T> () { return f => false; }
public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
}
}
Note: I've tested this approach with Portable Class Library project and have to use .Compile()
to make it work:
Where(predicate .Compile() );
You can continue chaining them like you've done.
results = results.Where (o => o.OrderStatus == OrderStatus.Open);
results = results.Where (o => o.InvoicePaid);
This represents an AND.
Surely:
if (useAdditionalClauses)
{
results =
results.Where(o => o.OrderStatus == OrderStatus.Open &&
o.CustomerID == customerID)
}
Or just another .Where()
call like this one (although I don't know why you would want to, unless it's split by another boolean control variable):
if (useAdditionalClauses)
{
results = results.Where(o => o.OrderStatus == OrderStatus.Open).
Where(o => o.CustomerID == customerID);
}
Or another reassignment to results
: `results = results.Where(blah).
Source: Stackoverflow.com