[英]Build query for IQueryable (EF4) from multiple parameters
I'm trying to build a single "Or" predicate from a list of predicates in the form List<Expression<Func<T, bool>>>
我正在尝试从
List<Expression<Func<T, bool>>>
形式的谓词列表中构建单个“或”谓词
public static IQueryable<T> Search<T>(this IQueryable<T> source, List<Expression<Func<T, bool>>> predicates = null)
where T : EntityObject
{
if (predicates == null || predicates.Count == 0)
return source;
else if (predicates.Count == 1)
return source.Where(predicates[0]);
else
{
var row = Expression.Parameter(typeof(T), "row");
var compoundExpression = predicates[0];
for (int i = 1; i < predicates.Count; i++)
{
compoundExpression = compoundExpression.Or(predicates[i]);
}
return source.Where(compoundExpression);
}
}
static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> lhs, Expression<Func<T, bool>> rhs)
{
var row = Expression.Parameter(typeof(T), "row");
var body = Expression.Or(
Expression.Invoke(lhs, row),
Expression.Invoke(rhs, row));
return Expression.Lambda<Func<T, bool>>(body, row);
}
But this is returning every row in my source?但这会返回我的源代码中的每一行吗?
For testing I am looking for c=>c.FullName.Contains("Smith") or c=>c.FullName.Contains("Jones")
为了测试,我正在寻找
c=>c.FullName.Contains("Smith") or c=>c.FullName.Contains("Jones")
I have tried amending to use PredicateBuilder but again it still returns every row in the source.我尝试修改以使用PredicateBuilder但它仍然返回源中的每一行。
public static IQueryable<T> Search<T>(this IQueryable<T> source, List<Expression<Func<T, bool>>> predicates = null)
where T : EntityObject
{
if (predicates == null || predicates.Count == 0)
return source;
else if (predicates.Count == 1)
return source.Where(predicates[0]);
else
{
var pb = PredicateBuilder.False<T>();
for (int i = 0; i < predicates.Count; i++)
{
pb = pb.Or(predicates[i]);
}
return source.AsExpandable().Where(pb);
}
}
Any assistance very gratefully received!非常感谢收到任何帮助!
The end result would be to allow AND's as well as OR's最终结果将是允许 AND 和 OR 的
eg c=>c.FullName.Contains("Dav") AND c=>c.CustomerType == 'Staff'例如 c=>c.FullName.Contains("Dav") AND c=>c.CustomerType == 'Staff'
Try尝试
public static IQueryable<T> Search<T>(this IQueryable<T> source, IEnumerable<Expression<Func<T, bool>>> predicates = null)
where T : EntityObject
{
if (predicates == null || !predicates.Any())
return source;
else
{
ParameterExpression p = Expression.Parameter(typeof(T), "p");
Expression<Func<T,Bool>> predicate =
Expression.Lambda<Func<T,Bool>(
predicates.Select(l => ReParameteriser(l.Body, l.Paramaters[0], p)
.Aggregate((b1,b2) => Expression.Or(b1,b2)),
new ParamaterExpression[]{p});
return source.Where(predicate);
}
}
public class ReParameteriser : ExpressionVisitor
{
ParameterExpression originalParameter;
ParameterExpression newParameter;
private ReParameteriser(){}
protected ReParameteriser (ParameterExpression originalParameter, ParameterExpression newParameter)
{
this.originalParameter = originalParameter;
this.new = newParameter;
}
public static Expression ReParameterise(Expression expression, ParameterExpression originalParameter, ParameterExpression newParameter)
{
return new ReParameteriser(original,newParameter).Visit(expression);
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == originalParameter)
return newParameter;
else
return node;
}
}
Note: The ExpressionVisitor class is .Net4 so if you want to target an earlier enviroment you will need to write your own.注意:ExpressionVisitor 类是 .Net4,因此如果您想针对较早的环境,则需要编写自己的环境。 The code for this is only a google away, but the usual resource is Matt Warren's blog http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx
这个代码只是一个谷歌,但通常的资源是马特沃伦的博客http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx
Sometimes the weekend does strange things to code!有时周末会做一些奇怪的事情来编码!
Not sure what I've done differently, but this is working:不确定我做了什么不同的事情,但这是有效的:
public static IQueryable<T> Search<T>(this IQueryable<T> source, List<Expression<Func<T, bool>>> predicates = null)
where T : EntityObject
{
if (predicates == null || predicates.Count == 0)
return source;
else if (predicates.Count == 1)
return source.Where(predicates[0]);
else
{
var query = PredicateBuilder.False<T>();
foreach (var predicate in predicates)
{
query = query.Or(predicate);
}
return source.AsExpandable().Where(query);
}
}
PredicateBuilder appears to be a great little bit of code. PredicateBuilder 似乎是一小段代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.