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

Posted

技术标签:

【中文标题】如何从数据库中获取可为空的 DateTime【英文标题】:How to get nullable DateTime out of the database 【发布时间】:2012-03-19 05:01:08 【问题描述】:

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

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

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

【问题讨论】:

怎么不工作?你有例外吗? 请不要在标题前加上标签。有标签是有原因的。 【参考方案1】:

如何创建辅助方法

private static DateTime? MyDateConverter(object o)

    return (o == DBNull.Value || o == null) ? (DateTime?)null : Convert.ToDateTime(o);

用法

MyDateConverter(sqldatareader[0])

【讨论】:

【参考方案2】:

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

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

【讨论】:

非常好的精确解决方案!从现在开始我将使用它而不是更麻烦的三元方法。 你能解释一下吗?我不明白什么以及为什么会有'?在日期时间之后。 @MDB 只是意味着它是一个可以为空的日期时间【参考方案3】:

只需使用:

System.Nullable<System.DateTime> yourVariableName;

让自己轻松一点:)

【讨论】:

这和数据库有什么关系?【参考方案4】:

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

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

在回答您的评论时,DataReaderItem 属性的数据类型是基础数据库类型的数据类型。它可以是 System.Data.SqlTypes.SqlDateTime 用于非空 SQL Server 数据库,或 System.DBNull 用于空列,或 System.Data.Odbc.OdbcTypes.SmallDateTime 用于 ODBC 数据库,或者几乎任何东西。您唯一可以依赖的是它的类型为object

这也是为什么我建议使用Convert.ToDateTime() 而不是对DateTime 的类型强制。不能保证 ODBC 或任何日期列可以强制转换为 .NET DateTime。我注意到您的评论指定了“sqldatareader”,并且 SQL Server System.Data.SqlTypes.SqlDateTime 确实可以强制转换为 System.DateTime,但您最初的问题并没有告诉我们。

有关使用DataReaders 的更多信息,请咨询MSDN。

【讨论】:

【参考方案5】:

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

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

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

【讨论】:

【参考方案6】:

前段时间,我为 DataRow 写了一堆扩展方法来做这种向下转换...因为我讨厌写重复的胡言乱语。用法很简单:

foreach( DataRow dr in someDataTable )

  DateTime? dt = dr.CastAsDateTimeNullable( "lastUpdated" ) ;
  int       id = dr.CastAsInt( "transactionID" ) ;
  // etc.

这是 DateTime 值的部分。为其他数据类型添加实现应该非常简单。如果有人愿意,对 DataReader 做同样的事情并不难。

我试图提出泛型方法,但是泛型方法的局限性使得很难或不可能做到并仍然获得我想要的行为(例如,null 值而不是 default(T) — 获得默认值用于区分 0null...困难的 SQL NULL。

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


【讨论】:

【参考方案7】:
DateTime? dt = null;

if (sqldatareader[0] != System.DbNull.Value)

    dt = (DateTime)sqldatareader[0];

【讨论】:

以上是关于如何从数据库中获取可为空的 DateTime的主要内容,如果未能解决你的问题,请参考以下文章

如何在 VB.NET 中将可为空的 DateTime 设置为空?

可为空的 DateTime 的 Datepicker 绑定不正确

将可为空的 DateTime 字段更新为 null 会导致默认 DateTime 值 (0001-01-01 00:00:00.0000000)

从类中获取可为空的 var

将可为空的 int 映射到可为空的 int + automapper

如果它为空或为空,如何从序列化中忽略可为空的属性?