Linq грешка общ параметър или заявката трябва да използва nullable тип

Получих тази грешка, когато използвам функция sum в LINQ:

Преобразуването към тип стойност „Decimal“ е неуспешно, защото материализираната стойност е нула. Или общият параметър на типа резултат, или заявката трябва да използва тип с възможност за нула.

GroupProduct.Where(a => a.Product.ProductID==1).Sum(Content => Content.Amount==null?0:Content.Amount),

person malik    schedule 16.01.2010    source източник
comment
Какъв е типът данни на свойството Amount?   -  person AnthonyWJones    schedule 16.01.2010
comment
DefaultIfempty е задължително да се използва, в случай че Where не връща никаква стойност, като по този начин се избягва NULL в този случай.   -  person baHI    schedule 11.09.2018


Отговори (5)


Това е, което обикновено използвам. Това ще покрие възможността Amount да е нула и също така ще покрие възможността за празен набор.

GroupProduct.Where(a => a.Product.ProductID == 1)
    .Select(c => c.Amount ?? 0) // select only the amount field
    .DefaultIfEmpty()  // if selection result is empty, return the default value
    .Sum(c => c)

DefaultIfEmpty() връща стойността по подразбиране, свързана с типа на Amount, която е int, в който случай стойността по подразбиране е 0.

person mendel    schedule 11.07.2012
comment
@Snađoshƒaӽ: благодаря, че поправихте правописните грешки в отговора ми. НО върнах нулевия коалесцентен оператор. DefaultIfEmpty ще върне единичен запис 0 САМО АКО първоначалният набор от резултати е празен, ако не е празен, но сумата е nullable и има null стойност, ще се провали без оператора за null coalescing. - person mendel; 06.03.2017

Опитахте ли следното:

GroupProduct.Where(a => a.Product.ProductID==1).Sum(Content => (decimal?)Content.Amount)

Кодът от моето приложение изглежда така:

var data = query.AsEnumerable().Select(row => TaskInfo.FetchTaskInfo(row,
      ctx.ObjectContext.Hours.Where(hour => hour.TaskId == row.TaskId).Sum(hour => (decimal?)hour.Duration),
      ctx.ObjectContext.Notes.Count(note => note.SourceType == (int)SourceType.Task && note.SourceId == row.TaskId)));
person mattruma    schedule 02.03.2011
comment
DefaultIfEmpty преди Sum е задължителен, ако няма върнат елемент на 1-во място. - person baHI; 11.09.2018

Бихте ли могли да изключите при източника?

var sum = GroupProduct.Where(a => a.Product.ProductID==1 && a.Amount != null)
            .Sum(a => (decimal)a.Amount);
person Marc Gravell    schedule 16.01.2010
comment
@malik - не разбирам; може ли да преформулирате този коментар? - person Marc Gravell; 16.01.2010
comment
Благодаря ви отново: Има две неща. когато използвам a.Product.ProductID обектът е null, мога ли да го проверя в linq заявка. - person malik; 16.01.2010
comment
Имам предвид в lamda израза мога ли да заредя препратката и мога ли да обработвам null в linq заявка. - person malik; 16.01.2010

Опитайте тази:

var sum = GroupProduct.Where(a => a.Product.ProductID==1).Sum(Content => (int?) Content.Amount);
sum = sum ?? 0;
person amiry jd    schedule 17.07.2011
comment
Да, това е друг начин за решаване, като позволите nullable типове вътре в LINQ и направите null coalesce в края. IMO DefaultIfEmpty е правилното решение, защото очакваме число като резултат в края, а не резултат с възможност за нула. - person baHI; 11.09.2018

Това изглежда, че трябва да работи (и обикновено работи), но се проваля, когато методът Where() върне нула:

decimal sum1 = GroupProduct
    .Where(a => a.Product.ProductID == 1)
    .Sum(c => c.Amount ?? 0);

Грешката: "The cast to value type 'Decimal' failed because the materialized value is null" се дължи на това, че методът Sum() връща нула (не нула) при сумиране върху празен набор.

Всяко от тези работи за мен:

decimal? sum2 = GroupProduct
    .Where(a => a.Product.ProductID == 1)
    .Sum(c => c.Amount);

decimal sum3 = GroupProduct
    .Where(a => a.Product.ProductID == 1)
    .Sum(c => c.Amount) ?? 0;
person Merenzo    schedule 17.01.2011
comment
DefaultIfEmpty преди Sum е задължителен, ако няма върнат елемент на 1-во място. - person baHI; 11.09.2018