如果您要为Linq查询添加“和”条件,则很容易这样做:
var q = MyTable;
if (condition1)
q = q.Where(t => t.Field1 == value1);
if (condition2)
q = q.Where(t => t.Field2 > t.Field3);
// etc.
当你想添加“或”条件时,有没有聪明的方法做同样的事情?
答案 0 :(得分:6)
您可以使用PredicateBuilder并使用它来构建基于Or
的表达式:
var predicate = PredicateBuilder.False<Product>();
predicate = predicate.Or (t => t.Field1 == value1);
predicate = predicate.Or (t => t.Field2 > t.Field3);
q = q.Where (predicate);
您可以在此处详细了解: http://www.albahari.com/nutshell/predicatebuilder.aspx
将Product
中的PredicateBuilder.False<Product>()
替换为您查询的对象。
请注意,您要从False
谓词开始,因为您要使用Or
。如果您需要And
谓词,则Yuo应从True
答案 1 :(得分:4)
使用以下内容:
var q = MyTable;
q = q.Where(
t => (condition1 && t.Field1 == value1) || (condition2 && t.Field2 > t.Field3));
答案 2 :(得分:2)
有一种方法可以使用表达式树。这样您就可以自己构建布尔表达式。这很简单,但是你需要 rebase 参数,因为否则它将引用原始的lambda表达式。请参阅下面的示例:
static void Main(string[] args)
{
var source = new List<int> { 1, 2, 3 };
var any = new List<Expression<Func<int, bool>>>();
any.Add(x => x == 1);
any.Add(x => x == 3);
foreach (var item in source.AsQueryable().WhereDisjunction(any))
{
Console.WriteLine(item);
}
}
class RewriteSingleParameterUsage : ExpressionVisitor
{
public ParameterExpression Parameter { get; set; }
protected override Expression VisitParameter(ParameterExpression node)
{
return Parameter;
}
}
public static IQueryable<T> WhereDisjunction<T>(this IQueryable<T> source, IList<Expression<Func<T, bool>>> any)
{
switch (any.Count)
{
case 0: return source;
case 1: return source.Where(any[0]);
default:
var p = Expression.Parameter(any[0].Parameters[0].Type, any[0].Parameters[0].Name);
var rw = new RewriteSingleParameterUsage { Parameter = p };
var expr = rw.Visit(any[0].Body);
for (int i = 1; i < any.Count; i++)
{
expr = Expression.Or(expr, rw.Visit(any[i].Body));
}
return source.Where(Expression.Lambda<Func<T, bool>>(expr, p));
}
}
在上面的例子中,我非常苛刻,我正在用这个用于创建新表达式的新参数替换任何参数。但是,鉴于此扩展方法的签名,实际上不应该使用参数调用此方法,以致它会导致错误。但是,如果涉及多个参数,则会出现问题。
答案 3 :(得分:2)
var q = MyTable;
var conditions = new List<Func<T, bool>>();
if (condition1)
conditions.Add(t => ...);
if (condition2)
conditions.Add(t => ...);
q.Where(x => conditions.Any(y => y(x)));
答案 4 :(得分:1)
这与我给出here
的答案相同正如Marc Gravell所说,它涉及表达式树组合。
这个article向您展示了如何做到这一点。初始设置它需要一些工作。但它值得。
替代解决方案是使用Predicate Builder。这篇文章没有很好地解释实际发生在幕后的情况。但上面的文章很好地解释了