2013-07-05 21 views
8

Tôi gần như ghét hỏi câu hỏi này có vẻ như nó đã được hỏi một triệu lần trước nhưng ngay cả với tôi nghiên cứu các câu hỏi khác tôi vẫn không thể hình dung điều này trong trường hợp của tôi.Nullable DateTime với SQLDataReader

Tôi đọc rằng DateTime là một loại nullable và tôi đã thử một vài ví dụ nhưng tôi đang cố gắng tìm ra nếu nó là NULL trong cơ sở dữ liệu SQLDATAREADER của tôi là không.

Lỗi

System.Data.SqlTypes.SqlNullValueException: Dữ liệu là Null. Phương thức hoặc thuộc tính này không thể được gọi trên các giá trị Null. '

DetailsClass

private DateTime? startingDate; 

public DateTime? StartingDate 
{ 
    get{ return startingDate; } 
    set{ startingDate = value; } 
} 

// constructor 
Public DetailsClass(DateTime? startingDate) 
{ 
    this.startingDate = startingDate; 
} 

DBClass

using (SqlConnection con = new SqlConnection(connectionString)) 
      using (SqlCommand cmd = con.CreateCommand()) 
      { 

       List<DetailsClass> details = new List<DetailsClass>(); 
       DetailsClass dtl; 
       try 
       { 
        con.Open(); 
        cmd.CommandText = "Stored Procedure Name"; 
        cmd.CommandType = CommandType.StoredProcedure; 
        cmd.Parameters.AddWithValue("@MyParameter", myparameter); 

        using (SqlDataReader reader = cmd.ExecuteReader()) 
        { 
         while (reader.Read()) 
         { 
          dtl = new DetailsClass((
           reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN"))), 
           reader.IsDBNull(1) ? null : reader.GetString(reader.GetOrdinal("EMAIL")), 
           reader.GetDateTime(reader.GetOrdinal("STARTINGDATE"))); 


          details.Add(dtl); 
         } 
         reader.Close(); 
         return details; 

        } 
       } 
+2

"Tôi đọc mà DateTime là một loại nullable" - bạn đọc sai. 'DateTime' không phải là nullable,' DateTime? 'Là. – Corak

+0

Tôi hiểu những gì bạn đang nói bây giờ tôi chỉ để lại dấu chấm hỏi – Jay

Trả lời

25

Dưới đây là một phương pháp helper để lấy giá trị ra khỏi đầu đọc

public static class ReaderExtensions { 

    public static DateTime? GetNullableDateTime(this SqlDataReader reader, string name){ 
     var col = reader.GetOrdinal(name); 
     return reader.IsDBNull(col) ? 
        (DateTime?)null : 
        (DateTime?)reader.GetDateTime(col); 
    } 
} 

Cập nhật về cách sử dụng để đáp ứng với bình luận

using (SqlConnection con = new SqlConnection(connectionString)) 
     using (SqlCommand cmd = con.CreateCommand()) 
     { 

      List<DetailsClass> details = new List<DetailsClass>(); 
      DetailsClass dtl; 
      try 
      { 
       con.Open(); 
       cmd.CommandText = "Stored Procedure Name"; 
       cmd.CommandType = CommandType.StoredProcedure; 
       cmd.Parameters.AddWithValue("@MyParameter", myparameter); 

       using (SqlDataReader reader = cmd.ExecuteReader()) 
       { 
        while (reader.Read()) 
        { 
         dtl = new DetailsClass((
          reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN"))), 
          reader.IsDBNull(1) ? null : reader.GetString(reader.GetOrdinal("EMAIL")), 
          reader.GetNullableDateTime("STARTINGDATE")); 


         details.Add(dtl); 
        } 
        reader.Close(); 
        return details; 

       } 
      } 

Cũng lưu ý bạn đang sử dụng reader.IsDBNull(1) và sau đó reader.GetOrdinal.Có lẽ nên là reader.IsDBNull(reader.GetOrdinal("EMAIL"))

+0

.IsDbNull là ném một ngoại lệ nói System.Data.Sqlclient.Sqldatareader không chứa một định nghĩa cho isdbnull bất kỳ ý tưởng – Jay

+0

@Jay Bởi vì tôi đã thực hiện một lỗi đánh máy, nó phải là 'IsDBNull', câu trả lời bây giờ sửa chữa –

+0

Im mất nó không thể tin tôi bỏ lỡ điều đó ... cảm ơn sự giúp đỡ của bạn thêm một câu hỏi mà bạn có; để kết thúc tuyên bố sau ("STARTINGDATE"); nhưng tôi cần phải đặt một, vì vậy tôi có thể thêm nhiều cột hơn cho người đọc và nếu bạn nhìn vào mã của tôi tôi không chỉ định startdatetime = cho người đọc ở bất cứ nơi nào tôi sẽ thực hiện nó theo cách này. – Jay

4

thay

DateTime startingDate; 

với

DateTime? startingDate; 

Dấu hỏi đánh dấu nó là giá trị nullable và người đọc của bạn có thể đặt bắt đầu thành null thay vì ném ngoại lệ.

bạn cũng có thể kiểm tra các giá trị null trong khi đọc bạn đang làm việc và thay thế các giá trị null với chuỗi rỗng

while(reader.read()) 
{ 
    //column is an int value of your column. I.e: if the column ist the 8th column, set column to 7 (0-based) 
    StartingDate = (reader.IsDBNull(column)) ? null : reader.GetOrdinal("STARTINGDATE")); 
//instead of null you could also return a specific date like 1.1.1900 or String.Empty 
} 
+0

Tôi đã chỉnh sửa mã của tôi dựa trên đề xuất của bạn tuy nhiên vẫn ném cùng một lỗi. Và tôi biết nó là trường này gây ra lỗi gây ra khi tôi đặt một giá trị trong cơ sở dữ liệu nó populates tốt. – Jay

+3

Mã này sai: reader.GetOrdinal lấy chỉ số nguyên của trường được đặt tên "STARTINGDATE", vậy tại sao bạn gán nó vào trường DateTime? – Joe

+0

details.StartingDate = reader.IsDBNull (15)? null: reader.GetDateTime (reader.GetOrdinal ("STARTINGDATE")); Không nhận được chuyển đổi ngầm định null và system.datetime – Jay

0

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

Tận dụng tối startingDate biến nullable, như thế này:

DateTime? startingDate; 

Bây giờ, khi truy xuất giá trị từ đối tượng SqlDataReader bạn cần sử dụng IsDbNull phương pháp, mà sẽ xác định nếu giá trị là NULL trở về từ cơ sở dữ liệu, như thế này:

if !reader.IsDBNull(reader.GetOrdinal("STARTINGDATE")) 
{ 
    startingDate = reader.GetDateTime(reader.GetOrdinal("STARTINGDATE")); 
} 
else 
{ 
    startingDate = null; 
} 

Lưu ý: Tôi không chắc chắn nơi bạn đang gán startingDate với giá trị đọc từ cơ sở dữ liệu, bởi vì nó không phải là được hiển thị trong mã được đăng. Đó là lý do tại sao tôi gán nó trực tiếp trong ví dụ của tôi, nhưng bạn có thể cần điều chỉnh vị trí của logic ví dụ.

+0

Cảm ơn phản hồi để đặt mã này trực tiếp vào trình đọc và MiddleName là gì? – Jay

+0

Tôi sẽ đăng mã của tôi như thế nào là chính xác để bạn có thể thấy chỉ là cố gắng để cho thấy rằng tôi đã làm một số công việc để cô lập những gì vấn đề của tôi để không nghĩ rằng tôi chỉ đến đây cho một bàn tay ra nhưng tôi đánh giá cao sự giúp đỡ của bạn nhờ – Jay

+0

Tôi đăng mã của tôi không phải tất cả của nó nhưng phần bạn cần tôi sẽ nghĩ rằng tôi có lớp chi tiết của tôi được liệt kê constructor của tôi và cũng lớp DB của tôi với mã cảm ơn một lần nữa – Jay

1

Bạn có thể vui lòng cho chúng tôi biết chính xác dòng nào đang ném lỗi trong khi gỡ lỗi. Nó sẽ được dễ dàng hơn.

if (! reader.IsDBNull(reader.GetOrdinal("STARTINGDATE"))) { 
    obj.startingDate = reader.GetDateTime(reader.GetOrdinal("STARTINGDATE")); 
} 

không cần chỉ định rõ ràng null nếu nó là DBNull, vì nó là một loại nullable do đó theo mặc định nó sẽ chứa null.

Ok, theo mã được cập nhật (lưu ý các ý kiến):

while (reader.Read()) { 
    dtl = new DetailsClass((reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN"))), 

    // here you are checking null for email 
    reader.IsDBNull(1) ? null : reader.GetString(reader.GetOrdinal("EMAIL")), 

    // here you are not checking null for startingdate ? 
    reader.GetDateTime(reader.GetOrdinal("STARTINGDATE"))); 
    details.Add(dtl); 
} 

Hãy thử nó theo cách tiết hơn:

while (reader.Read()) { 

    dtl = new DetailsClass(); 

    dtl.membershipgen = reader.IsDBNull(reader.GetOrdinal("MEMBERSHIPGEN")) ? null : reader.GetInt32(reader.GetOrdinal("MEMBERSHIPGEN")); 
    dtl.email = reader.IsDBNull(reader.GetOrdinal("EMAIL")) ? null : reader.GetString(reader.GetOrdinal("EMAIL")), 
    dtl.startingdate = reader.IsDBNull(reader.GetOrdinal("STARTINGDATE")) ? null : reader.GetDateTime(reader.GetOrdinal("STARTINGDATE"))); 

    details.Add(dtl); 
} 
+0

Đó là một bộ sưu tập danh sách vì vậy khi tôi gỡ lỗi nó làm nổi bật toàn bộ bộ sưu tập của tôi và nói lỗi trên tôi đã đăng nhưng sau khi làm như vậy một lần nữa, tôi đặt một giá trị trong cột startdate trong cơ sở dữ liệu mọi thứ hoạt động, vì vậy tôi biết đó là ngày bắt đầu trong sqldatareader của tôi – Jay

+0

cập nhật câu trả lời của tôi dựa trên chỉnh sửa gần đây của bạn – Abhitalks

+0

@ abhitalks bạn cần phải bỏ null của bạn như 'DateTime?' nếu không bạn sẽ nhận được một ngoại lệ cast ra khỏi trình biên dịch. –

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