У меня есть этот запрос:
int maxShoeSize = Workers
.Where(x => x.CompanyId == 8)
.Max(x => x.ShoeSize);
Что будет, maxShoeSize
если в компании 8 вообще не будет работников?
ОБНОВЛЕНИЕ:
Как я могу изменить запрос, чтобы получить 0, а не исключение?
maxShoeSize
?» если вы уже попробовали это.Ответы:
Ноль в
DefaultIfEmpty
не нужен.источник
Max()
пустой последовательности приводит к ошибке.Я знаю, что это старый вопрос, и принятый ответ работает, но этот вопрос ответил на мой вопрос о том, приведет ли такой пустой набор к исключению или
default(int)
результату.Однако принятый ответ, хотя он и работает, не является идеальным решением ИМХО, которое здесь не приводится. Таким образом, я предоставляю это в своем собственном ответе для выгоды любого, кто ищет это.
Оригинальный код ОП был:
Вот как я мог бы написать это, чтобы предотвратить исключения и предоставить результат по умолчанию:
Это приводит к типу возвращаемого значения
Max
функцииint?
, который разрешаетnull
результат, а затем??
заменяетnull
результат на0
.РЕДАКТИРОВАТЬ
Чтобы пояснить что-то из комментариев, Entity Framework в настоящее время не поддерживает
as
ключевое слово, поэтому способ написать его при работе с EF будет следующим:Поскольку имя
[TypeOfWorkers]
может быть длинным и утомительным для написания, я добавил метод расширения, чтобы выручить.Это только ручки
int
, но то же самое можно было бы сделатьlong
,double
или любой другой тип значения вам нужно. Использовать этот метод расширения очень просто: вы просто передаете свою функцию селектора и, необязательно, включаете значение, которое будет использоваться для нуля, по умолчанию равное 0. Таким образом, вышеприведенное можно переписать так:Надеюсь, это поможет людям еще больше.
источник
DefaultIfEmpty
ответ работает только тогда, когдаMax
не проводится оценка.Select
в качестве посредника, когда я просто собираюсь использовать агрегатную функцию, какMax
на результате. Я также думаю (я еще не проверял это), что сгенерированный SQL будет использовать дополнительный запрос на выборку, выполняя это, в то время как мой будет иметь дело с пустым набором, возвращая ноль. Спасибо за отзыв и отзыв! ;)ShoeSize
на самом деле в соответствующейUniform
сущности, я бы не использоватьWorkers.Where(x => x.CompanyId == 8).Select(x => x.Uniform).Max(x => x.ShoeSize)
, вместо этого я бы просто держать всю оценку вMax
функции:Workers.Where(x => x.CompanyId == 8).Max(x => x.Uniform.ShoeSize)
. Я предпочитаю использовать как можно меньше методов в своих запросах, чтобы позволить EF иметь наибольшую свободу при принятии решений о том, как эффективно создавать запросы. ;-)public static TResult MaxOrDefault<TElement, TResult>(this IQueryable<TElement> items, Expression<Func<TElement, TResult>> selector, TResult defaultValue = default) where TResult : struct => items.Select(selector).Max(item => (TResult?)item) ?? defaultValue;
Макс () ничего не вернет в этом случае.
Это вызовет InvalidOperationException, так как источник не содержит элементов.
источник
InvalidOperationException
случае, если объекты в списке имеют ненулевой тип: docs.microsoft.com/en-us/dotnet/api/…источник
Если это Linq to SQL, я не люблю его использовать,
Any()
потому что это приводит к нескольким запросам к SQL-серверу.Если
ShoeSize
это поле не обнуляемо, то использование только the.Max(..) ?? 0
не будет работать, но следующее будет:Это абсолютно не меняет испускаемый SQL, но он возвращает 0, если последовательность пуста, потому что он изменяет,
Max()
чтобы возвращатьint?
вместо вместоint
.источник
(при условии, что
ShoeSize
это типаint
)Если
Workers
это -DbSet
илиObjectSet
из Entity Framework, ваш начальный запрос будет выдаватьInvalidOperationException
, но не будет жаловаться на пустую последовательность, а будет жаловаться, что материализованное значение NULL не может быть преобразовано вint
.источник
Макс выбросит System.InvalidOperationException «Последовательность не содержит элементов»
источник
Примечание: запрос с
DefaultIfEmpty()
может быть значительно медленнее . В моем случае это был простой запрос с.DefaultIfEmpty(DateTime.Now.Date)
.Мне было лень его профилировать, но, очевидно, EF попытался получить все строки и затем принять
Max()
значение.Вывод: иногда обработка
InvalidOperationException
может быть лучшим выбором.источник
Вы можете использовать троичный внутри
.Max()
для обработки предиката и установить его значение;Вам нужно будет обрабатывать
Workers
коллекцию как пустую / пустую, если это возможно, но это будет зависеть от вашей реализации.источник
Вы можете попробовать это:
источник
Вы можете проверить, есть ли работники, прежде чем выполнять Max ().
источник