Получение правильных результатов из заявления LINQ - PullRequest
0 голосов
/ 25 октября 2019

Я использую оператор LINQ для получения набора данных из таблицы. Мне нужны данные из других связанных таблиц, чтобы получить набор, который я ищу. Я использую Entity Framework 6. Я не уверен в этом? Я мог бы помочь разобраться с этим. Я замаскировал свой код по деловым причинам, поэтому имена и значения таблиц фальшивы:

var result = POLICY_Record
                           .Include(pt => pt.POLICY_Primer)
                           .Include(pt => pt.POLICY_Primer.LOOKUP)
                           .Where(pt => pt.LOOKUP.ABBREV == "XXX")
                           .Where(pt => pt.DATE >= startDate && pt.DATE <= endDate)
                           .Where(pt => pt.LOOKUP.TYPE == "Y")
                           .Where(pt => pt.STATUS == 1)
                           .Where(pt => !excludedTransTypes.Contains(pt.FK_Value))
                           .Where(pt => stateconfigs.Contains(pt.STATE))
                           .ToList();

Моя проблема заключается в том, что может быть более 1 Policy_Record записей на Policy_Primer . Когда я запускаю это так, мне нужно копать глубоко, чтобы получить реальные результаты. Я должен перебрать результаты, чтобы получить запись Учебника для начинающих и затем получить Отчеты о политике.

Если я включу поиск по одному идентификатору учебника для начинающих, я сразу получу коллекцию записей для этого идентификатора. Если я этого не сделаю, я вынужден выполнить итерацию.

var result = POLICY_Record
                           .Include(pt => pt.POLICY_Primer)
                           .Include(pt => pt.POLICY_Primer.LOOKUP)
                           .Where(pt => pt.LOOKUP.ABBREV == "XXX")
                           .Where(pt => pt.DATE >= startDate && pt.DATE <= endDate)
                           .Where(pt => pt.LOOKUP.TYPE == "Y")
                           .Where(pt => pt.STATUS == 1)
                           .Where(pt => !excludedTransTypes.Contains(pt.FK_Value))
                           .Where(pt => stateconfigs.Contains(pt.STATE))
                           .Where(pt => pt.POLICY_Primer.NUMBER == Num)
                           .ToList();

Как ни странно, если я наведу курсор мыши на переменную результата, он отобразит ее как Список POLICY_Record . Я просто делаю это в неправильном порядке? Если я начну с учебника, условия не пройдены, и я не могу найти способ вернуть их.

1 Ответ

1 голос
/ 25 октября 2019

Странно, если я наведу указатель мыши на переменную результата, она отобразится в виде списка POLICY_Record. Я просто делаю это в неправильном порядке?

В этом нет ничего странного. Я подозреваю, что вы немного смущены тем, что делает Линк. Linq сокращает наборы, поэтому мы разложим ваш исходный запрос:

var result = POLICY_Record
                       .Include(pt => pt.POLICY_Primer)
                       .Include(pt => pt.POLICY_Primer.LOOKUP)
                       .Where(pt => pt.LOOKUP.ABBREV == "XXX")
                       .Where(pt => pt.DATE >= startDate && pt.DATE <= endDate)
                       .Where(pt => pt.LOOKUP.TYPE == "Y")
                       .Where(pt => pt.STATUS == 1)
                       .Where(pt => !excludedTransTypes.Contains(pt.FK_Value))
                       .Where(pt => stateconfigs.Contains(pt.STATE))
                       .ToList();

, начиная с ..

var result = POLICY_Record

Я предполагаю, что POLICY_Record в данном случае относится кDbSet вашей политики записи. Без Select или SelectMany ваше выражение Linq вернет сущности, с которых вы решили начать.

                       .Include(pt => pt.POLICY_Primer)
                       .Include(pt => pt.POLICY_Primer.LOOKUP)

Это говорит EF, что вы хотите загружать Policy_Primer и сущность Lookup этого учебника для начинающихдля каждой Policy_Record, которую он извлекает обратно. не требуется для того, чтобы иметь возможность записывать условия для этих полей или даже для проецирования вашего вывода. Это применимо только в том случае, если вы хотите вернуть сущности Policy_Record, и эти связанные сущности предварительно загружены и готовы к работе. (В отличие от отложенной загрузки по требованию, требующей дополнительных обращений к базе данных.)

                       .Where(pt => pt.LOOKUP.ABBREV == "XXX")
                       .Where(pt => pt.DATE >= startDate && pt.DATE <= endDate)
                       .Where(pt => pt.LOOKUP.TYPE == "Y")
                       .Where(pt => pt.STATUS == 1)
                       .Where(pt => !excludedTransTypes.Contains(pt.FK_Value))
                       .Where(pt => stateconfigs.Contains(pt.STATE))

Это ваши критерии. Вы говорите EF возвращать сущности Policy_Record, которые содержат данные, которые удовлетворяют всем этим условиям. Отсюда мы не основываем ни один из этих критериев на дополнительных загружаемых полями, таких как учебник для начинающих.

                       .ToList();

Это «выполняет» запрос и говорит EF вернуть все и все Policy_Records, которые удовлетворяют всемWhere условия и вместе с этими записями включают каждый из их Policy_Primer и Lookup этого учебника для начинающих.

Следующий вопрос будет таким: если это не то, что вы хотите, что вы на самом деле ожидаете увидеть? Добавив:

                       .Where(pt => pt.POLICY_Primer.NUMBER == Num)

Это говорит EF, что вы хотите только Policy_Records, где их связанный номер праймера соответствует вашему параметру. Вы все равно получите Policy_Records, только те, которые содержат учебник для начинающих с этим номером.

Проекция: Это, вероятно, недостающий фрагмент. Вышеуказанные запросы уменьшили набор Policy_Records, теперь мы используем проекцию, чтобы сообщить EF, что мы хотим вернуть. Обычно это делается с помощью Select. Например, если бы мы хотели использовать только праймеры политики для всех соответствующих политик, мы добавили бы:

                       .Select(pt => pt.POLICY_Primer)

, так что ...

var result = POLICY_Record
                       .Include(pt => pt.POLICY_Primer)
                       .Include(pt => pt.POLICY_Primer.LOOKUP)
                       .Where(pt => pt.LOOKUP.ABBREV == "XXX")
                       .Where(pt => pt.DATE >= startDate && pt.DATE <= endDate)
                       .Where(pt => pt.LOOKUP.TYPE == "Y")
                       .Where(pt => pt.STATUS == 1)
                       .Where(pt => !excludedTransTypes.Contains(pt.FK_Value))
                       .Where(pt => stateconfigs.Contains(pt.STATE))
                       .Select(pt => pt.POLICY_Primer)
                       .ToList();

Вместо списка записей политики мы получаемсписок учебников для начинающих. Мы можем добавить .Distinct() после Select, чтобы удалить дублирующиеся праймеры, если многие политики могут использовать один и тот же праймер.

Проекция полезна для уменьшения общего объема возвращаемых данных и выравнивания данных для отраженияпросто структура, которую мы хотим. Например, если мы отображаем список политик и соответствующих им праймеров, и нам нужны только некоторые поля, мы можем определить простую модель представления для результатов поиска и использовать Select для их заполнения:

.Select(pt => new PolicyViewModel
{
    PolicyNumber = pt.Policy_Number,
    Date = pt.Date,
    PrimerNumber = pt.Policy_Primer.Number,
    // ...
})

При использовании Select для проецирования, подобного этому, мы сообщаем EF точно, какие поля из каких сущностей мы хотим, и он будет составлять запрос для получения только этих деталей. Это позволяет базам данных более эффективно использовать индексы и сокращает время, память и пропускную способность, необходимые для запросов как на сервере базы данных, так и на сервере приложений. При использовании проекции таким способом вы также отрицаете необходимость использования Include. EF автоматически присоединится к таблицам для получения запрошенных вами данных. Вы можете включать сущности, но, как правило, этого не следует делать, так как это устраняет преимущества уменьшения размера набора данных, а также может оставить вас открытыми для отложенных загрузок и других неприятностей, если вы возвращаете сущности.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...