2016-01-22 20 views
5

Cố gắng lấy các giá trị được trả về từ cơ sở dữ liệu dựa trên tổng của một trường.MVC linq to sql sum

Nhưng nhận được tin nhắn này:

Dàn diễn viên để kiểu giá trị 'System.Decimal' thất bại vì các thể hóa giá trị là null. Tham số chung của loại kết quả là hoặc truy vấn phải sử dụng loại có thể không có giá trị.

Cơ sở dữ liệu không hợp lệ để không chứa bản ghi cho người dùng đó cho ngày đó, do đó tôi đã đi xuống tuyến đường không thể sử dụng. Trong những ngày tốt đẹp cũ tôi đã có thể xây dựng một thủ tục lưu trữ với `ISNULL` trong nó !!!

Đây là biểu hiện cơ bản tôi có:

decimal? foodCount = dbContext.fad_userFoods.Where(uf => uf.dateAdded == thisDate && uf.userID == thisGuid).Sum(uf=>(decimal?)uf.quantityAmount ?? 0m);

Googling nó đã đưa ra các định nghĩa nullable và sử dụng ?? với chữ "m" là số thập phân. Nhưng vẫn còn lỗi vẫn tồn tại!

Trợ giúp tập thể của bạn sẽ vô giá hơn bao giờ hết. Cảm ơn trước.

Trả lời

6

Sử dụng phương pháp DefaultIfEmpty. Điều này sẽ điền vào một 0 nếu không có giá trị nào cả.

decimal foodCount = dbContext.fad_userFoods 
    .Where(uf => uf.dateAdded == thisDate && uf.userID == thisGuid) 
    .Select(uf => uf.quantityAmount) 
    .DefaultIfEmpty() 
    .Sum(); 
+0

Bingo! Cảm ơn Maarten, điều này đã làm các trick. Vẫn còn rất nhiều để tìm hiểu về LINQ to sql! – stumcc

3

Sử dụng Convert.ToDecimal(), điều này sẽ xử lý vấn đề không có giá trị của bạn.

decimal foodCount = dbContext.fad_userFoods.Where(uf => uf.dateAdded == thisDate 
                && uf.userID == thisGuid) 
              .Sum(uf=> Convert.ToDecimal(uf.quantityAmount ?? 0m)); 

LINQ to Entities không nhận ra phương pháp 'System.Decimal ToDecimal (System.Decimal)' phương pháp, và phương pháp này có thể không được dịch sang một biểu hiện cửa hàng.

Edit:

decimal foodCount = dbContext.fad_userFoods.Where(uf => uf.dateAdded == thisDate 
                && uf.userID == thisGuid) 
              .Sum(uf=> { decimal result; 
                 decimal.TryParse(uf.quantityAmount,out result); 
                 return result;}); 
+0

tôi đã cố gắng mà trước đây nhưng chỉ cần thử nó một lần nữa và nhận được thông báo lỗi này: LINQ cho thực thể không nhận ra phương thức 'System.Decimal ToDecimal (System.Decimal)' phương pháp, và phương pháp này không thể được dịch sang một biểu thức cửa hàng. – stumcc

+0

@stumcc: Tôi đã cập nhật câu trả lời của mình, vui lòng xem. – Prabhat

3

Kể từ đó là một sum và không average bạn không thực sự quan tâm null-giá trị? Tại sao không chỉ đơn giản là loại bỏ các giá trị null?

decimal? foodCount = dbContext.fad_userFoods 
     .Where(uf => 
     uf.dateAdded == thisDate && 
     uf.userID == thisGuid && 
     uf.quantityAmount != null) 
     .Sum(uf=> uf.quantityAmount); 
+0

Về cơ bản, tôi đang tìm kiếm những thực phẩm có chứng nhận mà ai đó đã ăn trong một ngày. Vì vậy, có thể là người đó đã không ăn các loại thực phẩm đó, do đó tổng số tiền sẽ là 0 vì chúng không tồn tại trên bàn. – stumcc

+1

Có, nhưng trong trường hợp này null phải được chuyển đổi thành 0, điều này sẽ bằng không đếm nó chút nào. Do đó, việc loại trừ nó trong mệnh đề where sẽ thoát hoàn toàn khỏi vấn đề, nhưng vẫn cho cùng một số tiền. Ngoài ra, nó tránh bất kỳ sự hội tụ của các loại trong cơ sở dữ liệu. – smoksnes

2

Sự nhầm lẫn bắt nguồn từ thực tế là Sum trong LINQ To Entities được xử lý khác một chút so với LINQ To Objects. Mặc dù từ tuyên bố nó trông giống như gọi nó trên một let nói decimal sẽ trở về 0, khi tập hợp mục tiêu là trống thực sự chức năng SQL SUM trả về NULL, ngay cả khi cột mục tiêu là không nullable.

Khi bạn biết điều đó, có hai cách để giải quyết.

Hãy nói rằng chúng ta có một bảng với decimal cột và biểu hiện ban đầu là

table.Sum(item => item.Column) 

cách đầu tiên là để chuyển đổi nó bằng cách sử dụng mô hình chứa trong Maarten answer:

table.Select(item => item.Column).DefaultIfEmpty().Sum() 

Cách thứ hai là để chuyển đổi một cách rõ ràng loại không nullable thành nullable bên trong hàm và sau đó áp dụng toán tử không hợp lệ cho kết quả :

table.Sum(item => (decimal?)item.Column) ?? 0 

Cả hai cách đều hoạt động và tạo ra một kết quả giống nhau, vì vậy hãy sử dụng một cách phù hợp hơn với sở thích cá nhân của bạn.

Để hoàn chỉnh, áp dụng cách tiếp cận thứ hai trong trường hợp của bạn sẽ được về cơ bản di chuyển ?? 0 ngoài Sum gọi:

decimal foodCount = dbContext.fad_userFoods 
    .Where(uf => uf.dateAdded == thisDate && uf.userID == thisGuid) 
    .Sum(uf => (decimal?)uf.quantityAmount) ?? 0;