In LINQ one can build a LINQ query progressively as follows:
var context = new AdventureWorksDataContext();
// Step 1
var query = context.Customers.Where(d => d.CustomerType == "Individual");
// Step 2
query = query.Where(d => d.TerritoryID == 3);
The above query would yield an equivalent SQL statement with a WHERE clause comprising of two predicates combined together by an AND logical operator like the following:
SELECT * FROM Customers WHERE CustomerType = 'Individual' AND TerritoryID = 3
Can one build a LINQ query to yield an equivalent SQL statement, progressively
, such that the resulting query has a WHERE clause with the predicates combined together by an OR logical operator as follows?
SELECT * FROM Customers WHERE CustomerType = 'Individual' OR TerritoryID = 3
You would need to construct the filters first, and then combine the filters into a single lambda that you can use as the composed query:
var filters = new List<Expression<Func<YourType, bool>>>();
filters.Add(d => d.TerritoryID == 3);
filters.Add(d => d.CustomerType == "Individual");
...
var lambda = AnyOf(filters.ToArray());
// this is: d => d.TerrotoryID == 3 || d.CustomerType == "Individual";
var data = src.Where(lambda);
Using:
static Expression<Func<T,bool>> AnyOf<T>(
params Expression<Func<T,bool>>[] expressions)
{
if (expressions == null || expressions.Length == 0) return x => false;
if (expressions.Length == 1) return expressions[0];
var body = expressions[0].Body;
var param = expressions[0].Parameters.Single();
for (int i = 1; i < expressions.Length; i++)
{
var expr = expressions[i];
var swappedParam = new SwapVisitor(expr.Parameters.Single(), param)
.Visit(expr.Body);
body = Expression.OrElse(body, swappedParam);
}
return Expression.Lambda<Func<T, bool>>(body, param);
}
class SwapVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public SwapVisitor(Expression from, Expression to){
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
if you want it in two steps, you can use union:
var context = new AdventureWorksDataContext();
// Step 1
var query = context.Customers.Where(d => d.CustomerType == "Individual");
// step2
query = query.Union(context.Customers.Where(d => d.TerritoryID == 3));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With