我的 SQL Server 数据库包含可空的 DateTime 值。我该如何在 C# 应用程序中将它们转换为可空的 DateTime 对象?
以下是我认为会有效果的代码,但实际上不行:
DateTime? dt = (DateTime?) sqldatareader[0];
我的 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);
回答你的评论,DataReader
的 Item
属性数据类型是底层数据库类型的数据类型。它可以是非空 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])
DateTime? dt = DBConvert.To<datetime?>(sqldatareader[0]);
foreach( DataRow dr in someDataTable )
{
DateTime? dt = dr.CastAsDateTimeNullable( "lastUpdated" ) ;
int id = dr.CastAsInt( "transactionID" ) ;
// etc.
}
这里是关于 DateTime 值的代码片段。为其他数据类型添加实现应该相当容易。如果有兴趣,也可以对 DataReader 进行类似的操作。
我尝试想出通用方法,但泛型的限制使得这很难或不可能实现,并且仍然能够获得我想要的行为(例如,null
值而不是 default(T)
- 获取 SQL NULL 的默认值,这将使得区分 0
和 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
}
DateTime? dt = null;
if (sqldatareader[0] != System.DbNull.Value)
{
dt = (DateTime)sqldatareader[0];
}
只需使用:
System.Nullable<System.DateTime> yourVariableName;
让它变得简单 :)