Значение cast для значения "Int32" не выполнено, поскольку материализованное значение равно null
У меня есть следующий код. Я получаю сообщение об ошибке:
"Недействительный тип значения" Int32 "завершился неудачно, поскольку материализованное значение равно нулю. Либо общий параметр типа результата, либо запрос должен использовать тип с нулевым значением".
когда таблица CreditHistory не имеет записей.
var creditsSum = (from u in context.User
join ch in context.CreditHistory on u.ID equals ch.UserID
where u.ID == userID
select ch.Amount).Sum();
Как я могу изменить запрос для принятия нулевых значений?
Ответы
Ответ 1
Запрос linq-to-sql не выполняется как код, а скорее переведен в SQL. Иногда это "непроницаемая абстракция", которая приводит к неожиданному поведению.
Одним из таких случаев является обработка с нулевым значением, где могут быть неожиданные значения в разных местах. ...DefaultIfEmpty(0).Sum(0)
может помочь в этом (довольно простом) случае, где не может быть элементов, а sql SUM
возвращает null
, тогда как С# ожидать 0.
Более общий подход заключается в использовании ??
, который будет переведен на COALESCE
всякий раз, когда существует риск того, что сгенерированный SQL возвращает неожиданный null:
var creditsSum = (from u in context.User
join ch in context.CreditHistory on u.ID equals ch.UserID
where u.ID == userID
select (int?)ch.Amount).Sum() ?? 0;
Это первый запрос на int?
, чтобы сообщить компилятору С#, что это выражение действительно может вернуть null
, хотя Sum()
возвращает int
. Затем мы используем обычный оператор ??
для обработки случая null
.
Основываясь на этом ответе, я написал сообщение в блоге с подробностями для LINQ to SQL и LINQ to Entities.
Ответ 2
Чтобы разрешить нулевое поле Amount
, просто используйте нулевой оператор коалесцирования для преобразования нулей в 0.
var creditsSum = (from u in context.User
join ch in context.CreditHistory on u.ID equals ch.UserID
where u.ID == userID
select ch.Amount ?? 0).Sum();
Ответ 3
Вы используете функцию aggregate
, которая не получает элементы для выполнения действий, вы должны подтвердить, что запрос linq дает следующий результат:
var maxOrderLevel =sdv.Any()? sdv.Max(s => s.nOrderLevel):0
Ответ 4
Это сообщение об ошибке, когда я пытался выбрать из представления.
Проблема заключалась в том, что в последнее время недавно появились несколько новых нулевых строк (в столбце SubscriberId), и он не был обновлен в EDMX (сначала база EF).
Столбец должен был быть Nullable, чтобы он работал.
var dealer = Context.Dealers.Where(x = > x.dealerCode == dealerCode).FirstOrDefault();
Перед обновлением вида:
public int SubscriberId { get; set; }
После просмотра обновления:
public Nullable<int> SubscriberId { get; set; }
Сработало удаление и добавление представления в EDMX.
Надеюсь, это поможет кому-то.
Ответ 5
Я использовал этот код, и он отвечает правильно, только выходное значение обнуляется.
var packesCount = await botContext.Sales.Where(s => s.CustomerId == cust.CustomerId && s.Validated)
.SumAsync(s => (int?)s.PackesCount);
if(packesCount != null)
{
// your code
}
else
{
// your code
}
Ответ 6
Я вижу, что на этот вопрос уже дан ответ. Но если вы хотите, чтобы он был разделен на два утверждения, можно рассмотреть следующее.
var credits = from u in context.User
join ch in context.CreditHistory
on u.ID equals ch.UserID
where u.ID == userID
select ch;
var creditSum= credits.Sum(x => (int?)x.Amount) ?? 0;
Ответ 7
Получил эту ошибку в Entity Framework 6 с этим кодом во время выполнения:
var fileEventsSum = db.ImportInformations.Sum(x => x.FileEvents)
Обновление от LeandroSoares:
Используйте это для одиночного выполнения:
var fileEventsSum = db.ImportInformations.Sum(x => (int?)x.FileEvents) ?? 0
Оригинал:
Поменял на это и тогда все заработало:
var fileEventsSum = db.ImportInformations.Any() ? db.ImportInformations.Sum(x => x.FileEvents) : 0;