Ef core: последовательность не содержит элементов при выполнении MaxAsync - PullRequest
0 голосов
/ 08 января 2019

Я использую ядро ​​ef в своем проекте API ядра asp. Я должен найти индекс высшего порядка.

Пример:

Таблица данных: Id, ForeignId, OrderIndex

Итак, я делаю:

var highestOrderIndex = await _context
                .ExampleDbSet
                .Where(x =>
                    x.ForeignId == foreignId)
                .MaxAsync(x =>
                    x.OrderIndex);

Проблема в том, что в примере набора БД содержится 0 элементов. Это вызовет исключение: Sequence contains no element.

Есть ли элегантный способ сделать это? Потому что я не хочу получать все элементы из базы данных. И это должно быть асинхронно.

Спасибо

Ответы [ 3 ]

0 голосов
/ 08 января 2019

Выполнение AnyAsync, а затем MaxAsync приведет к двум отдельным вызовам базы данных. Вы можете сжать его в один, убедившись, что последовательность содержит минимальное значение «по умолчанию». Это полезный прием везде, где вы используете методы Linq Max / Min, а не только в коде базы данных:

context.ExampleDbSet
    .Where(w => w.ForeignId == foreignId)
    .Select(s => s.OrderIndex)
    .Concat(new[] { 0 })
    .MaxAsync();
0 голосов
/ 09 января 2019

На самом деле существует довольно элегантный (и более производительный по сравнению с предложенным в другом ответе, поскольку он выполняет только один запрос к базе данных) способ, использующий тот факт, что агрегатные методы, такие как Min, Max throw Sequence contains no element исключение только если используется с ненулевыми перегрузками, но обнуляемые перегрузки просто возвращают null.

Таким образом, все, что вам нужно, это преобразовать тип свойства, не допускающий значения NULL, в соответствующий тип NULL. Например, если тип OrderIndex равен int, единственное изменение в вашем запросе может быть

.MaxAsync(x => (int?)x.OrderIndex);

Обратите внимание, что это также изменит тип принимающей переменной highestOrderIndex на int?. Вы можете проверить null и отреагировать соответствующим образом, или вы можете просто объединить вызов агрегатной функции с оператором ?? и указать некоторое значение по умолчанию, например

var highestOrderIndex = (await _context.ExampleDbSet
    .Where(x => x.ForeignId == foreignId)
    .MaxAsync(x => (int?)x.OrderIndex)) ?? -1; // or whatever "magic" number works for you
0 голосов
/ 08 января 2019

Вы можете найти, если какие-либо записи существуют, и если они существуют, то найти макс. Примерно так:

var query = _context.ExampleDbSet
                .Where(x => x.ForeignId == foreignId);

var itemsExist = await query.AnyAsync();
int maxOrderIndex = 0;

if(itemsExist)
{
    maxOrderIndex = await query.MaxAsync(x => x.OrderIndex);
}

Здесь вам не нужно будет извлекать все элементы из базы данных, только проверить, существует ли запись, которая намного быстрее, и вы также можете оставить метод асинхронным.

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