在LINQ中,可以按如下方式逐步构建LINQ查询:
var context = new AdventureWorksDataContext();
// Step 1
var query = context.Customers.Where(d => d.CustomerType == "Individual");
// Step 2
query = query.Where(d => d.TerritoryID == 3);
上面的查询将产生一个等效的SQL语句,其WHERE子句包含两个由 AND 逻辑运算符组合在一起的谓词,如下所示:
SELECT * FROM Customers WHERE CustomerType = 'Individual' AND TerritoryID = 3
可以构建LINQ查询以生成等效的SQL语句progressively
,以便生成的查询具有WHERE子句,其中谓词由 OR 逻辑运算符组合在一起,如下所示?
SELECT * FROM Customers WHERE CustomerType = 'Individual' OR TerritoryID = 3
答案 0 :(得分:11)
您需要先构建过滤器,然后将过滤器组合成一个可用作组合查询的lambda:
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);
使用:
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);
}
}
答案 1 :(得分:1)
如果你想分两步,你可以使用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));
答案 2 :(得分:1)
虽然您可以直接执行此类操作,但我使用LinqKit库,这使得这种渐进式查询构建非常简单:
你最终会得到:
var context = new AdventureWorksDataContext();
// Step 1
var query = context.Customers.Where(d => d.CustomerType == "Individual");
// Step 2
query = query.Or(d => d.TerritoryID == 3);
我正在研究的系统需要很多,LinqKit是一个重要的救生员。你可以找到它here。
(注意:无论如何,我与LinqKit的开发者没有任何关系 - 只是一个粉丝。)
答案 3 :(得分:0)
要在不使用动态linq lib的情况下完成您的要求,您可以在where子句中为每个测试定义表达式,然后使用它们来构建lambda表达式:
Expression<Func<Customer, bool>> isIndividualCustomer = c => c.CustomerType == "Individual";
Expression<Func<Customer, bool>> territoryIdIs3 = c => c.TerritoryID == 3;
Expression<Func<Car, bool>> customerIsIndividualOrOfTerritoryId3 = Expression.Lambda<Func<Customer, bool>>(
Expression.Or(isIndividualCustomer.Body, territoryIdIs3.Body), isIndividualCustomer.Parameters.Single());
用法:
var query = context.Customers.Where(customerIsIndividualOrOfTerritoryId3);