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

本文关键字:null DateTime 获取 数据库 | 更新日期: 2023-09-27 18:26:06

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

这就是我认为的样子,但事实并非如此:

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

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

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.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,但您最初的问题并没有告诉我们这一点。

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

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

var dt = sqldatareader[0] as DateTime?;

如何创建辅助方法

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

使用

MyDateConverter(sqldatareader[0])

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

一旦你实现了这个类,你就可以这样使用它:

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

不久前,我为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
}
DateTime? dt = null;
if (sqldatareader[0] != System.DbNull.Value)
{
    dt = (DateTime)sqldatareader[0];
}

只需使用:

System.Nullable<System.DateTime> yourVariableName;

让自己轻松一点:)