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

时间:2012-02-29 17:22:10

标签: c# sql-server datetime nullable sqldatareader

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

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

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

7 个答案:

答案 0 :(得分:29)

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

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

答案 1 :(得分:27)

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

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

在回答您的评论时,Item的{​​{1}}属性的数据类型是基础数据库类型的数据类型。对于非空SQL Server数据库,它可以是DataReader,对于空列,可以是System.Data.SqlTypes.SqlDateTime,对于ODBC数据库可以是System.DBNull,或者实际上几乎任何东西。您唯一可以依赖的是System.Data.Odbc.OdbcTypes.SmallDateTime类型。

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

有关使用System.DateTime的更多信息,请参阅MSDN

答案 2 :(得分:2)

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

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

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

答案 3 :(得分: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

}

答案 4 :(得分:1)

如何创建帮助方法

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

用法

MyDateConverter(sqldatareader[0])

答案 5 :(得分:0)

DateTime? dt = null;

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

答案 6 :(得分:0)

只需使用:

System.Nullable<System.DateTime> yourVariableName;

让自己轻松自如:)