2012-02-29 14 views
12

SQL Serverデータベースにはnull可能なDateTime値が含まれています。どうすればC#でアプリケーションのnullable DateTimeオブジェクトに変換できますか?nullable DateTimeをデータベースから取得する方法

これは私がそれのように見えると思うだろうものですが、それはしません:

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

どのように動作しないのですか?例外はありますか? – jrummell

+1

タイトルにタグをつけないでください。理由のためのタグがあります。 – cadrell0

答えて

21

SQLのNULLは、.NETヌルと同じではありません。あなたはSystem.DBNull.Valueと比較する必要があります:あなたのコメントへの答えで

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

は、DataReaderItemプロパティのデータ型は、基礎となるデータベースの種類のことです。 NULL以外のSQL Serverデータベースの場合はSystem.Data.SqlTypes.SqlDateTime、NULL列の場合はSystem.DBNull、ODBCデータベースの場合はSystem.Data.Odbc.OdbcTypes.SmallDateTime、または実際には何でもあります。あなたが頼りにできるのは、タイプがobjectであることだけです。

これは、DateTimeに型変換の代わりにConvert.ToDateTime()を使用することを提案する理由です。 ODBCまたは任意の日付列を.NET DateTimeに強制することはできません。私はあなたのコメントが "sqldatareader"を指定しており、System.Data.SqlTypes.SqlDateTimeは確かにSystem.DateTimeに強制されるかもしれませんが、あなたの元の質問はそれを私たちに教えてくれませんでした。

DataReaderの使用の詳細については、MSDNを参照してください。

2

「null」ではなく「DBNull」であるかどうかを確認する必要があります。私は私のブログに小さなヘルパークラスを投稿:http://improve.dk/archive/2007/10/08/handling-dbnulls.aspx

をあなたはクラスを実装したら、あなたはこのようにそれを使用します。

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

偉大な心は[ほとんど]似ていると思います! B^D –

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値ではなく、SQLのNULLのためdefault(T) —取得既定値たかった動作を取得するために作られました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

+0

これは私にとって素晴らしい仕事でした。 – alundy

+0

非常に正確な解決策!私は今よりも面倒な三項法の代わりにこれを使用します。 – Baxter

0

ちょうど使用:

System.Nullable<System.DateTime> yourVariableName; 

は自分のことが簡単になります:)

+0

これはデータベースとは何が関係していますか? – deW1

0

どのようにヘルパーメソッドを作成する方法について

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

使用

MyDateConverter(sqldatareader[0]) 
関連する問題