динамически добавлять несколько выражений linq во время выполнения - PullRequest
1 голос
/ 08 июля 2011

У меня есть два похожих метода, которые берут объект критерия (тупой объект со списком свойств), вызывают метод «CreateExpression» для этого объекта критерия, а затем используют возвращенное выражение для фильтрации результатов.

Один из моих примеров имеет аргумент только одного критерия, и он работает без проблем.Мой второй метод берет List<Criteria>, а затем пытается выполнить итерацию по каждому критерию в списке, сгенерировать выражение для него, а затем «и» его к предыдущему выражению.Предполагается, что конечным результатом будет одно большое выражение, которое я затем смогу использовать в своем запросе linq.

Однако этот второй метод не работает.Когда я использую отладчик, я могу видеть предикат с его телом и лямбда-выражением внутри, но когда он попадает на сервер SQL, все, что он отправляет, - это оператор выбора без предложений 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 ]

1 голос
/ 08 июля 2011

Хорошо, я понял это.

Мне нужно было использовать метод 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());
                }
            }

И теперь это работает! Я нашел подробности об этом и по этому другому вопросу .

0 голосов
/ 08 июля 2011

Внутри вашего для каждого цикла объявите локальную переменную в этом блоке и установите ее значение равным значению переменной цикла.

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