我有两个类似的方法,它们采用一个条件对象(带有属性列表的哑对象),在该条件对象上调用“CreateExpression”方法,然后使用返回的表达式来过滤结果。
我的一个例子只有一个标准的论点,它没有问题。我的第二个方法采用List<Criteria>
,然后尝试遍历列表中的每个条件,并为其生成表达式,然后“和”它到前一个表达式。最终结果应该是我可以在我的linq查询中使用的一个大表达式。
然而,第二种方法不起作用。当我使用调试器时,我可以在内部看到带有body和lambda表达式的谓词,但是当它到达SQL服务器时,它发送的只是一个select语句,根本没有where子句。
这是有效的方法(使用一个标准对象):
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;
}
我正在使用Predicate Builder来生成初始表达式。我不相信这些方法存在问题,因为它们使用第一种(单一)方法。
有谁知道这里发生了什么?
修改 我忘了说后端是实体框架。
答案 0 :(得分:1)
好的,我明白了。
我需要在我在附加谓词的行中调用谓词的所有位置使用“Expand()”方法。这是我的第二种方法中foreach循环的新修复版本:
foreach (Criteria.SegmentCriteria x in myCriteria)
{
Criteria.SegmentCriteria item = x;
if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAll)
{
predicate = predicate.Expand().And<Segment>(CreateCriteriaExpression(item).Expand());
customPropertiesPredicate = customPropertiesPredicate.Expand().And<Segment>(CreateCriteriaExpressionForCustomProperties(item).Expand());
}
else if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAny)
{
predicate = predicate.Expand().Or<Segment>(CreateCriteriaExpression(item).Expand());
customPropertiesPredicate = customPropertiesPredicate.Expand().Or<Segment>(CreateCriteriaExpressionForCustomProperties(item).Expand());
}
}
现在它有效!我在其他question上也找到了有关此内容的详细信息。
答案 1 :(得分:0)
在每个循环中,在该块中声明一个局部变量,并将其值设置为循环变量的值。
foreach (Criteria.SegmentCriteria x in myCriteria)
{
Criteria.SegmentCriteria temp = x;
if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAll)
{
predicate = predicate.And(CreateCriteriaExpression(temp).Expand());
customPropertiesPredicate = customPropertiesPredicate.And(CreateCriteriaExpressionForCustomProperties(temp).Expand());
}
else if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAny)
{
predicate = predicate.Or(CreateCriteriaExpression(temp).Expand());
customPropertiesPredicate = customPropertiesPredicate.Or(CreateCriteriaExpressionForCustomProperties(temp).Expand());
}
}