在运行时动态追加多个 linq 表达式
我有两个类似的方法,它们采用条件对象(具有属性列表的哑对象),在该条件对象上调用“CreateExpression”方法,然后使用返回的表达式来过滤结果。
我的一个例子只包含一个标准的论证,而且它的工作没有问题。我的第二种方法采用 List
,然后尝试迭代列表中的每个条件,并为其生成表达式,然后将其“与”到前一个表达式。最终结果应该是一个大表达式,然后我可以在 linq 查询中使用它。
然而,第二种方法不起作用。当我使用调试器时,我可以在内部看到谓词及其主体和 lambda 表达式,但是当它到达 SQL Server 时,它发送的只是一条根本没有 where 子句的 select 语句。
这是一种有效的方法(使用一个标准对象):
public static List<Segment> GetByCriteria(Criteria.SegmentCriteria myCriteria)
{
List<Segment> result = null;
List<Segment> qry = db.Segments.AsExpandable<Segment>().Where<Segment>(CreateCriteriaExpression(myCriteria)).ToList<Segment>();
qry = qry.Where<Segment>(CreateCriteriaExpressionForCustomProperties(myCriteria).Compile()).ToList<Segment>();
if (qry != null && qry.Count != 0)
{
result = qry;
}
return result;
}
这是一种不起作用的方法:
public static List<Segment> GetByCriteria(List<Criteria.SegmentCriteria> myCriteria, Common.MultipleCriteriaMatchMethod myMatchMethod)
{
List<Segment> result = null;
var predicate = PredicateBuilder.True<Segment>();
var customPropertiesPredicate = PredicateBuilder.True<Segment>();
foreach (Criteria.SegmentCriteria x in myCriteria)
{
if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAll)
{
predicate = predicate.And(CreateCriteriaExpression(x).Expand());
customPropertiesPredicate = customPropertiesPredicate.And(CreateCriteriaExpressionForCustomProperties(x).Expand());
}
else if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAny)
{
predicate = predicate.Or(CreateCriteriaExpression(x).Expand());
customPropertiesPredicate = customPropertiesPredicate.Or(CreateCriteriaExpressionForCustomProperties(x).Expand());
}
}
List<Segment> qry = db.Segments.AsExpandable<Segment>().Where<Segment>(predicate.Expand()).ToList<Segment>();
qry = qry.Where<Segment>(customPropertiesPredicate.Expand().Compile()).ToList<Segment>();
if (qry != null && qry.Count != 0)
{
result = qry;
}
return result;
}
我正在使用 谓词生成器 生成初始表达式。我不认为这些方法有问题,因为它们适用于第一个(单一)方法。
有谁知道这是怎么回事?
编辑 忘了说了,后端是实体框架。
I have two similar methods that take a criteria object (dumb object with a list of properties), call a "CreateExpression" method on that criteria object, and then use the returned expression to filter results.
One of my examples has an argument of only one criteria, and it works with no problem. My second method takes a List<Criteria>
and then attempts to iterate through each criteria in the list, and generate the expression for it, and then "and" it to the previous expression. The end result is supposed to be one big expression that I can then use in my linq query.
However, this second method is not working. When I use the debugger, I can see the predicate with it's body and lambda expression internally, but when it hits the SQL server, all it sends is a select statement with no where clauses at all.
Here is the method that works (with one criteria object):
public static List<Segment> GetByCriteria(Criteria.SegmentCriteria myCriteria)
{
List<Segment> result = null;
List<Segment> qry = db.Segments.AsExpandable<Segment>().Where<Segment>(CreateCriteriaExpression(myCriteria)).ToList<Segment>();
qry = qry.Where<Segment>(CreateCriteriaExpressionForCustomProperties(myCriteria).Compile()).ToList<Segment>();
if (qry != null && qry.Count != 0)
{
result = qry;
}
return result;
}
Here is the one that doesn't work:
public static List<Segment> GetByCriteria(List<Criteria.SegmentCriteria> myCriteria, Common.MultipleCriteriaMatchMethod myMatchMethod)
{
List<Segment> result = null;
var predicate = PredicateBuilder.True<Segment>();
var customPropertiesPredicate = PredicateBuilder.True<Segment>();
foreach (Criteria.SegmentCriteria x in myCriteria)
{
if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAll)
{
predicate = predicate.And(CreateCriteriaExpression(x).Expand());
customPropertiesPredicate = customPropertiesPredicate.And(CreateCriteriaExpressionForCustomProperties(x).Expand());
}
else if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAny)
{
predicate = predicate.Or(CreateCriteriaExpression(x).Expand());
customPropertiesPredicate = customPropertiesPredicate.Or(CreateCriteriaExpressionForCustomProperties(x).Expand());
}
}
List<Segment> qry = db.Segments.AsExpandable<Segment>().Where<Segment>(predicate.Expand()).ToList<Segment>();
qry = qry.Where<Segment>(customPropertiesPredicate.Expand().Compile()).ToList<Segment>();
if (qry != null && qry.Count != 0)
{
result = qry;
}
return result;
}
I am using Predicate Builder to generate the initial expression. I don't believe there is a problem with those methods since they work with the first (singular) method.
Does anyone know what's going on here?
Edit
I forgot to say that the backend is entity framework.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,我明白了。
我需要在附加谓词的行中调用谓词的所有位置使用“Expand()”方法。这是我的第二种方法中 foreach 循环的新固定版本:
现在它可以工作了!我也在其他 问题。
Ok, I figured it out.
I needed to use the "Expand()" method on ALL places where I was calling a predicate in the lines where I was appending the predicate. Here is the new fixed version of the foreach loop in my second method:
And now it works! I found details about this also on this other question.