如果向当前查询添加更多限制,则可以在c#中轻松创建动态查询。
var list = new List<Item>();
var q = list.AsQueryable();
q = q.Where(x => x.Size == 3);
q = q.Where(x => x.Color == "blue");
在这种情况下,添加每个新谓词与前一个执行AND操作。之前的结果相当于:
q = list.Where(x => x.Size == 3 && x.Color == "blue");
是否可以使用OR代替AND来实现相同的结果?
q = list.Where(x => x.Size == 3 || x.Color == "blue");
我们的想法是使用OR运算符连接可变数量的表达式。
预期结果需要写入一些与以下伪代码类似的内容:
var conditions = new List<Func<Item, bool>>();
然后迭代条件来构建类似的东西:
foreach(var condition in conditions)
finalExpression += finalExpression || condition;
答案 0 :(得分:1)
感谢RaphaëlAlthaus给出了以下链接:
http://www.albahari.com/nutshell/predicatebuilder.aspx
谓词构建器是解决方案。您可以使用它从Nuget安装LinqKit。在该URL中,您还可以找到此类的实现。
注意:为了使这个工作与LinqToSql或LinqToEntities一起使用,必须使用“AsExpandable()”方法转换IQueriable对象,对于内存对象,它不是必需的
答案 1 :(得分:1)
另一个可能的解决方案,特别是当有人不想使用外部库时,使用表达式树。
添加以下表达式扩展名:
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);
return Expression.Lambda<Func<T, bool>>(
Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
作为一个例子,假设你有一个Container实体,它有InnerContainer嵌套实体,有两个属性Name和Id。然后您可以通过以下方式使用它:
Expression<Func<Container, bool>> whereQuery = c => c.InnerContainer.Name == "Name1";
whereQuery = whereQuery.Or(c => c.InnerContainer.Name == "Name2");
whereQuery = whereQuery.Or(c => c.InnerContainer.Id == 0);
var result = query
.Where(whereQuery)
.ToList();
实现此类查询将导致以下SQL:
SELECT [x].[Id], [x].[InnerContainerId]
FROM [Containers] AS [x]
LEFT JOIN [InnerContainer] AS [x.InnerContainer] ON [x].[InnerContainerId] = [x.InnerContainer].[Id]
WHERE [x.InnerContainer].[Name] IN (N'Name1', N'Name2') OR ([x].[InnerContainerId] = 0)
这样你就可以在一个集合中持有lambda并循环遍历它们。