如何制作化合物“;或“;Linq中的子句
本文关键字:子句 Linq 何制作 化合物 | 更新日期: 2023-09-27 17:59:39
如果要将"and"条件添加到Linq查询中,很容易这样做:
var q = MyTable;
if (condition1)
q = q.Where(t => t.Field1 == value1);
if (condition2)
q = q.Where(t => t.Field2 > t.Field3);
// etc.
当你想添加"或"条件时,有什么聪明的方法可以做同样的事情吗?
您可以使用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
将PredicateBuilder.False<Product>()
中的Product
替换为查询的对象。
请注意,您从False
谓词开始,因为您希望使用Or
。如果您想要And
谓词,Yuo应该从True
开始
使用以下内容:
var q = MyTable;
q = q.Where(
t => (condition1 && t.Field1 == value1) || (condition2 && t.Field2 > t.Field3));
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)));
有一种方法可以做到这一点,那就是使用表达式树。通过这种方式,您可以自己构建布尔表达式。这是非常直接的,但棘手的部分是,您需要重新设置参数的基础,否则它将引用原始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));
}
}
在上面的例子中,我非常苛刻,我有效地将任何参数替换为用于创建新表达式的单个新参数。然而,考虑到这个扩展方法的签名,应该不可能用参数来调用这个方法,这样会导致错误。然而,如果涉及多个参数,这将是一个问题。
这与我在这里给出的答案相同
正如Marc Gravell所说,它涉及到表达式树的组合。
这篇文章向您展示了如何做到这一点。最初设置它需要一些工作。但这是值得的。
另一种解决方案是使用谓词生成器。这篇文章并没有很好地解释幕后到底发生了什么。但是上面的文章很好地解释了