在运行时动态附加多个linq表达式

时间:2011-07-08 17:57:55

标签: c# linq entity-framework dynamic-linq predicatebuilder

我有两个类似的方法,它们采用一个条件对象(带有属性列表的哑对象),在该条件对象上调用“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来生成初始表达式。我不相信这些方法存在问题,因为它们使用第一种(单一)方法。

有谁知道这里发生了什么?

修改 我忘了说后端是实体框架。

2 个答案:

答案 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());
            }
        }