Is there anyway to join LINQ where clauses as OR ?
无论如何加入LINQ的条款是OR吗?
var ints = new [] { 1, 3, 5, 7 };
var query = from i in ints select i;
query = query.Where (q => q == 3);
query = query..Where (q => q == 7);
What I want is the ability to dynamically add where clauses but make them use OR instead of AND
我想要的是能够动态添加where子句但是使用OR而不是AND
7 个解决方案
#1
12
If you want to stay with your strong-typing Linq queries you should look into LinqKit and predicate building. I have used this for something similar and found it to work well with And / Or stacking of filters.
如果你想继续使用强类型的Linq查询,你应该查看LinqKit和谓词构建。我已经将它用于类似的东西,并发现它与And / Or堆叠过滤器配合得很好。
Check out the C#4.0/3.0 in a Nutshell excerpt for more in depth info. Here is a snip from my code:
在Nutshell摘录中查看C#4.0 / 3.0以获取更多深入信息。这是我的代码中的一个片段:
//Setup the initial predicate obj then stack on others:
basePredicate = basePredicate.And(p => false);
var predicate1 = PredicateBuilder.True<Person>();
foreach (SearchParms parm in parms)
{
switch (parm.field)
{
case "firstname":
predicate1 = predicate1.And(p => p.FirstName.Trim().ToLower().Contains(sValue));
break;
//etc...
}
}
//Run a switch based on your and/or parm value to determine stacking:
if (Parm.isAnd) {
basePredicate = basePredicate.And(predicate1);
} else {
basePredicate = basePredicate.Or(predicate1);
}
#2
2
How about something like this?
这样的事怎么样?
var query = from i in ints where CheckConditions(i) select i;
public bool CheckConditions(int i)
{
var conditions = WhereConditions; //an IEnumerable<Func<int, bool>> of dynamically added conditions
foreach (var condition in conditions)
{
if (condition(i)) return true;
}
return false;
}
You can probably expand this to be a bit cleverer but that's sort of how I'd do it.
你可以扩展这个有点聪明,但这就是我的方式。
EDIT: Sorry the first example was an AND, have changed it now to be an OR. So the first time it encounters a passing condition it returns true.
编辑:对不起,第一个例子是AND,现在已将其更改为OR。所以第一次遇到传递条件时它返回true。
#3
2
Using ExpressionVisitor
to help to build the expression base on two expressions with OR/AND relationship. This answer is from Jeffery Zhao's blog.
使用ExpressionVisitor帮助构建基于具有OR / AND关系的两个表达式的表达式。这个答案来自Jeffery Zhao的博客。
internal class ParameterReplacer : ExpressionVisitor
{
public ParameterReplacer(ParameterExpression paramExpr)
{
this.ParameterExpression = paramExpr;
}
public ParameterExpression ParameterExpression { get; private set; }
public Expression Replace(Expression expr)
{
return this.Visit(expr);
}
protected override Expression VisitParameter(ParameterExpression p)
{
return this.ParameterExpression;
}
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> one, Expression<Func<T, bool>> another)
{
var candidateExpr = Expression.Parameter(typeof(T), "candidate");
var parameterReplacer = new ParameterReplacer(candidateExpr);
var left = parameterReplacer.Replace(one.Body);
var right = parameterReplacer.Replace(another.Body);
var body = Expression.And(left, right);
return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> one, Expression<Func<T, bool>> another)
{
var candidateExpr = Expression.Parameter(typeof(T), "candidate");
var parameterReplacer = new ParameterReplacer(candidateExpr);
var left = parameterReplacer.Replace(one.Body);
var right = parameterReplacer.Replace(another.Body);
var body = Expression.Or(left, right);
return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
}
#4
0
You can using Union method:
您可以使用Union方法:
var ints = new [] { 1, 3, 5, 7 };
var query = ints.Where(q => q == 3);
query = query.Union(ints.Where(q => q == 7));
#5
-2
Are you talking about specifying more than one condition in the lambda?
你在谈论在lambda中指定多个条件吗?
query = query.Where(q => q == 3 ||
q == 7);
#6
-3
try this
尝试这个
var ints = new [] { 1, 3, 5, 7 };
var ints = new [] {1,3,5,7};
var query = ints.select(X=>X).where(X=>X==3||X==7);
var query = ints.select(X => X).where(X => X == 3 || X == 7);
#7
-3
I am trying to do something similar. Here's what I came up with:
我正在尝试做类似的事情。这就是我想出的:
//various test cases
bool useTestCase1 = true;
bool useTestCase2 = true;
bool useTestCase3 = false;
query = query.Where(q =>
(q == 3 && useTestCase1 ) ||
(q == 7 && useTestCase2 ) ||
(q == 10 && useTestCase3 )
);
#1
12
If you want to stay with your strong-typing Linq queries you should look into LinqKit and predicate building. I have used this for something similar and found it to work well with And / Or stacking of filters.
如果你想继续使用强类型的Linq查询,你应该查看LinqKit和谓词构建。我已经将它用于类似的东西,并发现它与And / Or堆叠过滤器配合得很好。
Check out the C#4.0/3.0 in a Nutshell excerpt for more in depth info. Here is a snip from my code:
在Nutshell摘录中查看C#4.0 / 3.0以获取更多深入信息。这是我的代码中的一个片段:
//Setup the initial predicate obj then stack on others:
basePredicate = basePredicate.And(p => false);
var predicate1 = PredicateBuilder.True<Person>();
foreach (SearchParms parm in parms)
{
switch (parm.field)
{
case "firstname":
predicate1 = predicate1.And(p => p.FirstName.Trim().ToLower().Contains(sValue));
break;
//etc...
}
}
//Run a switch based on your and/or parm value to determine stacking:
if (Parm.isAnd) {
basePredicate = basePredicate.And(predicate1);
} else {
basePredicate = basePredicate.Or(predicate1);
}
#2
2
How about something like this?
这样的事怎么样?
var query = from i in ints where CheckConditions(i) select i;
public bool CheckConditions(int i)
{
var conditions = WhereConditions; //an IEnumerable<Func<int, bool>> of dynamically added conditions
foreach (var condition in conditions)
{
if (condition(i)) return true;
}
return false;
}
You can probably expand this to be a bit cleverer but that's sort of how I'd do it.
你可以扩展这个有点聪明,但这就是我的方式。
EDIT: Sorry the first example was an AND, have changed it now to be an OR. So the first time it encounters a passing condition it returns true.
编辑:对不起,第一个例子是AND,现在已将其更改为OR。所以第一次遇到传递条件时它返回true。
#3
2
Using ExpressionVisitor
to help to build the expression base on two expressions with OR/AND relationship. This answer is from Jeffery Zhao's blog.
使用ExpressionVisitor帮助构建基于具有OR / AND关系的两个表达式的表达式。这个答案来自Jeffery Zhao的博客。
internal class ParameterReplacer : ExpressionVisitor
{
public ParameterReplacer(ParameterExpression paramExpr)
{
this.ParameterExpression = paramExpr;
}
public ParameterExpression ParameterExpression { get; private set; }
public Expression Replace(Expression expr)
{
return this.Visit(expr);
}
protected override Expression VisitParameter(ParameterExpression p)
{
return this.ParameterExpression;
}
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> one, Expression<Func<T, bool>> another)
{
var candidateExpr = Expression.Parameter(typeof(T), "candidate");
var parameterReplacer = new ParameterReplacer(candidateExpr);
var left = parameterReplacer.Replace(one.Body);
var right = parameterReplacer.Replace(another.Body);
var body = Expression.And(left, right);
return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> one, Expression<Func<T, bool>> another)
{
var candidateExpr = Expression.Parameter(typeof(T), "candidate");
var parameterReplacer = new ParameterReplacer(candidateExpr);
var left = parameterReplacer.Replace(one.Body);
var right = parameterReplacer.Replace(another.Body);
var body = Expression.Or(left, right);
return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
}
#4
0
You can using Union method:
您可以使用Union方法:
var ints = new [] { 1, 3, 5, 7 };
var query = ints.Where(q => q == 3);
query = query.Union(ints.Where(q => q == 7));
#5
-2
Are you talking about specifying more than one condition in the lambda?
你在谈论在lambda中指定多个条件吗?
query = query.Where(q => q == 3 ||
q == 7);
#6
-3
try this
尝试这个
var ints = new [] { 1, 3, 5, 7 };
var ints = new [] {1,3,5,7};
var query = ints.select(X=>X).where(X=>X==3||X==7);
var query = ints.select(X => X).where(X => X == 3 || X == 7);
#7
-3
I am trying to do something similar. Here's what I came up with:
我正在尝试做类似的事情。这就是我想出的:
//various test cases
bool useTestCase1 = true;
bool useTestCase2 = true;
bool useTestCase3 = false;
query = query.Where(q =>
(q == 3 && useTestCase1 ) ||
(q == 7 && useTestCase2 ) ||
(q == 10 && useTestCase3 )
);