2012-02-29 45 views
12

我的SQL Server數據庫包含可爲空的DateTime值。如何將它們轉換爲C#中的應用程序中的可空對象DateTime對象?如何從數據庫中獲得可空的DateTime

這就是我認爲這將是什麼樣子,但它並不:

DateTime? dt = (DateTime?) sqldatareader[0]; 
+1

如何在不工作?你有例外嗎? – jrummell 2012-02-29 17:23:42

+1

請勿在標籤前添加標籤。有標籤是有原因的。 – cadrell0 2012-02-29 17:32:22

回答

21

SQL空值是不一樣的一個.NET空;你必須要比較System.DBNull.Value:

object sqlDateTime = sqldatareader[0]; 
DateTime? dt = (sqlDateTime == System.DBNull.Value) 
    ? (DateTime?)null 
    : Convert.ToDateTime(sqlDateTime); 

在回答您的意見,一個DataReaderItem屬性的數據類型是基礎數據庫類型。對於非空SQL Server數據庫,它可以是System.Data.SqlTypes.SqlDateTime,對於空列可以是System.DBNull,對於ODBC數據庫可以是System.Data.Odbc.OdbcTypes.SmallDateTime,或者對於任何事情都可以。唯一可以依賴的是它是object

這也是爲什麼我建議使用Convert.ToDateTime()而不是類型強制DateTime。不保證ODBC或任何日期列可以強制爲.NET DateTime。我注意到你的評論指定了一個「sqldatareader」,並且SQL Server System.Data.SqlTypes.SqlDateTime確實可以被強制爲System.DateTime,但你原來的問題並沒有告訴我們。請致電MSDN

2

您需要檢查值「是DBNull」而不是僅爲null。我貼一個小的輔助類,在我的博客:http://improve.dk/archive/2007/10/08/handling-dbnulls.aspx

一旦你實現類,你可以使用這樣的:

DateTime? dt = DBConvert.To<datetime?>(sqldatareader[0]); 
+0

偉大的思想認爲[主要]相似! B^D – 2012-02-29 17:52:03

0
DateTime? dt = null; 

if (sqldatareader[0] != System.DbNull.Value) 
{ 
    dt = (DateTime)sqldatareader[0]; 
} 
1

前一段時間,我寫了一堆的擴展方法的DataRow做這種向下轉換......因爲我討厭寫重複的動作。用法很簡單:

foreach(DataRow dr in someDataTable) 
{ 
    DateTime? dt = dr.CastAsDateTimeNullable("lastUpdated") ; 
    int  id = dr.CastAsInt("transactionID") ; 
    // etc. 
} 

這是DateTime值的一部分。爲其他數據類型添加實現應該非常簡單。如果人們傾向於這麼做,那麼對DataReader做同樣的事情並不困難。

我試圖想出通用的方法,但是在方式仿製藥的限制完成,因此很難或不可能做到,仍然可以得到我想要的行爲(例如,null值而不是default(T) —爲SQL NULL值獲取默認值這將區分0null ...困難)。

public static class DataRowExtensions 
{ 

    #region downcast to DateTime 

    public static DateTime CastAsDateTime(this DataRow row , int index) 
    { 
    return toDateTime(row[index]) ; 
    } 
    public static DateTime CastAsDateTime(this DataRow row , string columnName) 
    { 
    return toDateTime(row[columnName]) ; 
    } 

    public static DateTime? CastAsDateTimeNullable(this DataRow row , int index) 
    { 
    return toDateTimeNullable(row[index]); 
    } 
    public static DateTime? CastAsDateTimeNullable(this DataRow row , string columnName) 
    { 
    return toDateTimeNullable(row[columnName]) ; 
    } 

    #region conversion helpers 

    private static DateTime toDateTime(object o) 
    { 
    DateTime value = (DateTime)o; 
    return value; 
    } 

    private static DateTime? toDateTimeNullable(object o) 
    { 
    bool hasValue = !(o is DBNull); 
    DateTime? value = (hasValue ? (DateTime?) o : (DateTime?) null) ; 
    return value; 
    } 

    #endregion 

    #endregion downcast to DateTime 

    // ... other implementations elided .. for brevity 

} 
23

我最近發現這一招,這很簡單:

DateTime? dt = sqldatareader[0] as DateTime?; 
+4

回答你自己的問題並不愚蠢。 – Homer 2012-04-11 15:06:23

+0

這對我很好。 – alundy 2013-01-21 10:25:06

+0

非常好的精確解決方案!我將從現在開始使用它,而不是更繁瑣的三元方法。 – Baxter 2014-12-10 14:42:58

0

只需使用:

System.Nullable<System.DateTime> yourVariableName; 

讓它在自己容易:)

+0

這與數據庫有什麼關係? – deW1 2014-01-22 21:59:46

0

有關創建的helper方法

如何
private static DateTime? MyDateConverter(object o) 
{ 
    return (o == DBNull.Value || o == null) ? (DateTime?)null : Convert.ToDateTime(o); 
} 

使用

MyDateConverter(sqldatareader[0])