如何从数据库中获取可以为空的DateTime

我的SQL Server数据库包含可空的DateTime值。 如何在C#中的应用程序中将它们转换为可以为空的DateTime对象?

这是我认为它会是什么样子,但它没有:

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

SQL null与.NET null不同; 你必须与System.DBNull.Value进行比较:

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

在回答您的注释时, DataReaderItem属性的数据类型是底层数据库类型的数据类型。 它可以是非空SQL Server数据库的System.DBNull ,或空列的System.Data.Odbc.OdbcTypes.SmallDateTime ,或ODBC数据库的System.Data.Odbc.OdbcTypes.SmallDateTime ,或者几乎任何东西。 你唯一可以依赖的是它是object类型。

这也是我建议使用Convert.ToDateTime()而不是类型强制到DateTime 。 无法保证可以将ODBC或任何日期列强制转换为.NET DateTime 。 我注意到你的注释指定了一个“sqldatareader”,并且SQL Server System.Data.SqlTypes.SqlDateTime确实可以被强制转换为System.DateTime ,但你原来的问题没有告诉我们。

有关使用DataReader的更多信息,请参阅MSDN 。

我最近发现了这个技巧,很简单:

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

您需要检查值“是否为DBNull”而不是null。 我在我的博客上发布了一个小帮手类: http : //improve.dk/archive/2007/10/08/handling-dbnulls.aspx

实现该类后,您可以像这样使用它:

 DateTime? dt = DBConvert.To(sqldatareader[0]); 

不久之前,我为DataRow写了一堆扩展方法来做这种向下转换…因为我不喜欢写重复的文件。 用法很简单:

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

这是DateTime值的部分。 为其他数据类型添加实现应该是非常简单的。 如果人们如此倾向于对DataReader做同样的事情并不困难。

我尝试提出generics方法,但是generics方式的限制使得很难或不可能做到并且仍然得到我想要的行为(例如, 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 } 
 DateTime? dt = null; if (sqldatareader[0] != System.DbNull.Value) { dt = (DateTime)sqldatareader[0]; } 

只需使用:

 System.Nullable yourVariableName; 

让自己轻松:)

如何创建帮助方法

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

用法

 MyDateConverter(sqldatareader[0])