2012-01-05 35 views
5

Tôi đang cố gắng sử dụng lại cùng mã mà tôi đã luôn sử dụng nhưng hiện tại nó đang gặp lỗi.Đối tượng dễ vỡ phải có giá trị # 2

Tôi lặp thông qua các bảng người dùng khác nhau, và trong đó tôi làm điều này:

DateTime dcdt = (DateTime)u.DateCreated; 
DateTime lldt = (DateTime)u.LastLogon; 
userRow["DateCreated"] = dcdt.ToShortDateString(); 

bên trong vòng lặp. Tôi nhận được lỗi:

System.InvalidOperationException: Nullable object must have a value. 

Lỗi nổi bật "lldt" dòng, thay vì "dcdt" mà đến trước. Điều đó thật lạ lẫm trong chính nó. Cả hai trường này trong cơ sở dữ liệu "cho phép null" được chọn. Và cả hai có thể là null hoặc không có thể là null.

Hai giá trị này đều được liệt kê là Ngày giờ? các loại thông qua intellisense.

Tôi không hiểu tại sao ASP.NET từ chối cho phép tôi xuất trống trong các ngày không có. Nếu nó là rỗng/null, thì logic sẽ gợi ý rằng ASP.NET chỉ nên in không có gì.

Tôi có thể giả sử như thế nào để xuất các ngày tháng không? Tôi đã thử thêm nếu các câu lệnh để ngăn chặn cố gắng để cast null DateTimes, nhưng nó không giúp đỡ, nó không có ý nghĩa.

Trả lời

12

Như bạn đã nói, loại dữ liệu của u.LastLogonDateTime?. Điều này có nghĩa là nó có thể có hoặc không có giá trị. Bằng cách truyền tới DateTime, bạn đang yêu cầu nó có giá trị. Trong trường hợp này, nó không.

Tùy thuộc vào những gì bạn đang cố gắng để làm gì với nó, bạn có thể muốn kiểm tra HasValue tài sản:

userRow["LastLogon"] = u.LastLogin.HasValue ? 
         (object) u.LastLogin.ToShortDateString() : DBNull.Value; 

Nếu cột cơ sở dữ liệu LastLogon của bạn là loại DateTime, sau đó bạn sẽ có thể phải làm:

userRow["LastLogon"] = u.LastLogin.HasValue ? 
         (object) u.LastLogin.Value : DBNull.Value; 
+0

Vì vậy, tôi phải làm gì với nó? Tôi không bỏ? Tôi có tiếp tục sử dụng ShortDateString() trên DateTime không? thay vì DateTime? – Dexter

+0

Xem cập nhật của tôi nếu loại cột là DateTime –

+1

Chính xác cách 'u.LastLogon.Value.ToShortDateString()' không hoạt động? –

1

Vấn đề là .NET null không giống với SQL NULL. SQL Null là System.DBNull. Vì vậy, nó là một giá trị [không null] trong .NET.

+0

Vì vậy, làm thế nào để làm cho nó để nó phải in hoặc không có gì hoặc in một ngày nếu có? – Dexter

+0

Kỹ thuật Frazell là chính xác, nhưng tôi khá chắc chắn bản dịch sẽ diễn ra tự động. Nếu cột datetime của bạn là null, bạn sẽ thấy một .net null. Nhưng đó không phải là vấn đề, Bạn phải viết một số mã để kiểm tra nếu nó là null và in không có gì. Như bạn đã thấy, cách nhỏ gọn nhất để làm điều này là với? ASP.NET sẽ không làm điều này cho bạn. –

1

Có vẻ như bạn đang cố gắng gọi phương thức (dcdt.ToShortDateString()) trên DateTime? không có giá trị (nó thực sự là null). Hãy thử điều này:

dcdt.HasValue ? dcdt.ToShortDateString() : String.Empty; 

EDIT (Chỉ cần đọc lại câu hỏi): Ngoài ra, đừng cố gắng chuyển sang DateTime. Bảo toàn giá trị rỗng.

EDIT # 2 (dựa trên ý kiến):

Hãy thử điều này:

if (dcdt.HasValue) 
{ userRow["DateCreated"] = dcdt.ToShortDateString(); } 
else 
{ userRow = DbNull.Value } 
+0

u.LastLogon.HasValue? u.LastLogon.Value.ToShortDateString(): DBNull.Value; hoặc u.LastLogon.HasValue? u.LastLogon.ToShortDateString(): DBNull.Value; từ chối làm việc. Nó sẽ không biên dịch như thế. LastLogon là một loại DateTime ?. – Dexter

+0

Thats vì DBNull.Value không phải là một chuỗi-biểu thức phải trả về một kiểu dữ liệu nhất quán. Tôi sẽ chỉnh sửa một cách thích hợp –

+0

Tôi nghĩ rằng tôi đã giải quyết nó. Tôi đã sử dụng điều này: userRow ["LastLogon"] = u.LastLogon.HasValue? u.LastLogon.Value.ToShortDateString(): String.Empty; – Dexter

1

Bạn cần phải làm một cái gì đó như sau trong mã truy cập dữ liệu của bạn:

DataTable dt  = ExecuteSomeQuery() ; 
object  value = dt.Rows[0]["nullable_datetime_column"] ; 
DateTime? instance = value != null && value is DateTime ? (DateTime?)value : (DateTime?)null) ; 

Nếu cột trả về là NULL, nó sẽ được trả về như là một System.DBNull, nếu không nó sẽ được trả về như một thể hiện của DateTime (hoặc bất kỳ loại ánh xạ thích hợp là — int, string, vv).Do đó, bạn cần phải kiểm tra kiểu đối tượng được trả về từ truy vấn trước khi thử truyền nó.

+0

Đã là DateTime? kiểu. Bây giờ tôi muốn chuyển đổi nó thành một String sử dụng hàm ShortDateTimeString trong lớp DateTime. Nó sẽ không cho phép tôi. – Dexter

+1

Trong trường hợp đó, 'string s = instance.HasValue? instance.Value.ToString(): ""; 'nên thực hiện thủ thuật. –

+0

Đúng vậy. Nhưng ai đó khác đánh bại bạn với câu trả lời theo đúng định dạng. – Dexter

1

Tôi thấy rằng Dexter hỏi anh ấy nên đi về nó như thế nào. Vâng, tôi sẽ tạo ra một phần mở rộng.

static class DateTimeExtensions 
{ 
    public static string ToString(this DateTime? dateTime, string format) 
    { 
     return dateTime.HasValue ? dateTime.Value.ToString(format) : String.Empty; 
    } 
} 

Và sau đó bạn có thể làm:

DateTime? dt = null; 
DateTime? dt2 = DateTime.Now; 
Console.WriteLine(dt.ToString("dd-MM-yy")); 
Console.WriteLine(dt2.ToString("dd-MM-yy")); 

Lưu ý rằng tôi có thể gọi phương thức mở rộng trên một loại nullable nếu đối tượng là null.

+0

đây là một giải pháp tốt đẹp –

Các vấn đề liên quan