2013-07-05 64 views
8

我幾乎不想問這個問題,好像它已被問過一百萬次之前,但即使在我研究另一個問題時,我仍然無法解決這個問題。SQLDataReader的可以爲空的日期時間

我看到DateTime是一個可爲空的類型,我嘗試了幾個例子,但我想弄清楚它是否爲數據庫中的NULL,我的SQLDATAREADER失敗了。

錯誤

System.Data.SqlTypes.SqlNullValueException:數據爲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

「我讀了日期時間是可空類型」 - 你讀錯了。 'DateTime'不能爲空,'DateTime?'是。 – Corak

+0

我明白你在說什麼,我只是留下了問號 – Jay

回答

25

這裏是一個輔助方法,從讀者中獲得的價值了

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

如何響應使用評論

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; 

       } 
      } 

還要注意你正在使用reader.IsDBNull(1)然後更新reader.GetOrdinal。可能應該是reader.IsDBNull(reader.GetOrdinal("EMAIL"))

+0

.IsDbNull拋出一個異常說System.Data.Sqlclient.Sqldatareader不包含isdbnull的定義任何想法 – Jay

+0

@Jay因爲我犯了一個錯字,它應該是'IsDBNull',現在更正了回答 –

+0

Im失去它不能相信我錯過了...感謝您的幫助,您還有一個問題;在(「STARTINGDATE」)之後結束聲明;但我需要放一個,所以我可以添加更多的列給讀者,如果你看我的代碼,我不分配startdatetime =任何地方的讀者,我將如何實現它這種方式。 – Jay

4
替換

DateTime startingDate; 

DateTime? startingDate; 

問號將其標記爲可爲空值,您的讀者應該能夠將startingdate設置爲null,而不是拋出異常。

你也可以檢查空值,而你的讀者正在與空字符串替換空值

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

我根據你的建議編輯了我的代碼,但仍然拋出相同的錯誤。而且我知道這是導致錯誤的原因,當我在它填充的數據庫中放置一個值的時候,會導致錯誤原因。 – Jay

+3

此代碼錯誤:reader.GetOrdinal獲取指定字段「STARTINGDATE」的整數索引,那麼爲什麼將它分配給DateTime字段? – Joe

+0

details.StartingDate = reader.IsDBNull(15)? null:reader.GetDateTime(reader.GetOrdinal(「STARTINGDATE」));收到沒有隱式轉換null和system.datetime – Jay

0

試試這個:

充分利用startingDate變量nullable,就像這樣:

DateTime? startingDate; 

現在,當從SqlDataReader對象中檢索到值時,您需要使用IsDbNull方法,這將確定該值是NULL從數據庫中回來,就像這樣:

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

注:我不知道你在哪裏分配startingDate從數據庫中讀取的值,因爲它不是顯示在發佈的代碼中。這就是爲什麼我直接在我的例子中分配它,但你可能需要調整示例邏輯的位置。

+0

感謝您將此代碼直接放置在閱讀器中的響應以及MiddleName是什麼? – Jay

+0

我會發布我的代碼它是如何正是如此,你可以看到只是試圖表明,我做了一些工作,以隔離我的問題,所以不認爲我只是來到這裏舉手,但我感謝你的幫助,謝謝 – Jay

+0

我發佈我的代碼不是所有的,但你應該需要的部分我會認爲我有我的細節類列出我的構造函數和我的數據庫類與代碼再次感謝 – Jay

1

請您在調試時能告訴我們究竟是哪一行拋出錯誤。這會更容易。

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

無需顯式地指定爲null,如果它是DBNull的,因爲它是一個可空類型,因此默認情況下它會包含空值。

好,按你更新的代碼(注意註釋):

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

讓我們試着用更詳細的方式:

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

它是一個列表集合,所以當我調試它突出顯示我的整個集合並說上面的錯誤我發佈,但這樣做後搞亂一旦我把數據庫中的起始日期列中的值一切正常,所以我知道它是我的sqldatareader中的起始日期行 – Jay

+0

根據您最近的編輯更新了我的答案 – Abhitalks

+0

@ abhitalks你需要將null作爲'DateTime?'強制轉換,否則你會從編譯器中得到一個強制異常。 –

相關問題