2011-07-28 33 views
156

Tôi có mã sau đây. Tôi gặp lỗi:Giá trị đúc thành loại giá trị 'Int32' không thành công do giá trị vật hoá là null

"The cast to value type 'Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type."

khi bảng Tín dụng không có hồ sơ.

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(); 

Làm cách nào để sửa đổi truy vấn để chấp nhận giá trị null?

Trả lời

272

Một truy vấn LINQ-to-sql không thực hiện như mã, nhưng thay vì dịch sang SQL. Đôi khi đây là một "trừu tượng bị rò rỉ" mang lại hành vi bất ngờ.

Một trường hợp như vậy là xử lý không có giá trị, trong đó có thể có các giá trị không mong muốn ở những vị trí khác nhau. ...DefaultIfEmpty(0).Sum(0) có thể giúp đỡ trong việc này (khá đơn giản) trường hợp, nơi có thể có không có các yếu tố và sql của SUM lợi nhuận null trong khi C# mong đợi 0.

Một cách tiếp cận tổng quát hơn là sử dụng ?? đó sẽ được dịch sang COALESCE bất cứ khi nào có một nguy cơ rằng SQL tạo trả về một null bất ngờ:

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; 

này đầu tiên phôi để int? để nói với trình biên dịch C# rằng biểu thức này thực sự có thể trở null, mặc dù Sum() trả về một int. Sau đó, chúng tôi sử dụng toán tử thông thường ?? để xử lý trường hợp null.

Dựa trên câu trả lời này, tôi đã viết blog post với chi tiết cho cả LINQ to SQL và LINQ to Entities.

+3

cảm ơn Anders, giải pháp với DefaultIfEmpty (0) .Sum() hoạt động tốt cho tôi. Tôi cũng đã thử giải pháp thứ hai với (int?) ... ?? 0 ..., nhưng nó ném cùng một ngoại lệ như trước đây .. – zosim

+0

Cuối cùng đã có xung quanh để kiểm tra điều này và điều chỉnh nó, vì vậy bây giờ phiên bản thứ hai hoạt động quá. –

+0

Hàm Sum() và các hàm tổng hợp khác sẽ trả về giá trị rỗng khi được áp dụng cho tập dữ liệu trống. Trái ngược với định nghĩa của chúng, trên thực tế chúng trả về một phiên bản nullable của kiểu cơ bản. – Suncat2000

8

Để cho phép một Amount lĩnh vực nullable, chỉ cần sử dụng các nhà điều hành coalescing null để chuyển đổi null để 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(); 
+1

khi tôi sử dụng đầu của bạn, trình biên dịch nói: Operator '? ? ' không thể áp dụng cho các toán hạng kiểu 'int' và 'int'. tôi có quên gì không? – zosim

+0

@zosim: Đó là lý do để thêm dàn diễn viên vào 'int? 'Trước tiên. –

+0

tôi đã thêm int ?, nhưng ngoại lệ tương tự. Tôi sẽ biết ơn bạn, khi bạn sẽ có env dev. để kiểm tra những gì sai trong cú pháp này. – zosim

5

Bạn đang sử dụng aggregate chức năng mà không nhận được các mục cần thực hiện thao tác, bạn phải xác minh truy vấn LINQ được đưa ra một số kết quả như sau:

var maxOrderLevel =sdv.Any()? sdv.Max(s => s.nOrderLevel):0 
+9

Điều này sẽ làm cho sdv thực hiện hai lần. Mà không phải là những gì bạn muốn cho IQueryables – Ody

1

Tôi đang sử dụng đoạn mã này và Nó phản ứng một cách chính xác, chỉ giá trị đầu ra là nullable.

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 
          } 
1

Tôi thấy câu hỏi này đã được trả lời. Nhưng nếu bạn muốn nó được chia thành hai câu, sau đây có thể được xem xét.

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; 
+1

Làm việc cho tôi ... –

2

Đã có thông báo lỗi này khi tôi đang cố chọn từ chế độ xem.

Vấn đề là quan điểm gần đây đã đạt được một số hàng null mới (trong cột SubscriberId), và nó chưa được cập nhật trong EDMX (cơ sở dữ liệu EF trước).

Cột phải là loại Không có khả năng hoạt động.

var dealer = Context.Dealers.Where (x => x.dealerCode == dealerCode).FirstOrDefault();

Trước khi xem refresh:

public int SubscriberId { get; set; } 

Sau khi xem refresh:

public Nullable<int> SubscriberId { get; set; } 

Xóa và thêm quan điểm trở lại trong EDMX làm việc.

Hy vọng nó sẽ giúp ai đó.

0

Got lỗi này trong Entity Framework 6 với mã này trong thời gian chạy:

var fileEventsSum = db.ImportInformations.Sum(x => x.FileEvents) 

Thay đổi này và sau đó nó làm việc:

var fileEventsSum = db.ImportInformations.Any() ? db.ImportInformations.Sum(x => x.FileEvents) : 0; 
Các vấn đề liên quan