Как получить значение NULL DateTime из базы данных
Моя база данных SQL Server содержит значения NULL-времени с нулевым значением. Как я могу преобразовать их в объект с нулевым значением DateTime в моем приложении на С#?
Это то, что я думаю, это будет выглядеть, но это не так:
DateTime? dt = (DateTime?) sqldatareader[0];
Ответы
Ответ 1
SQL-null - это не то же самое, что .NET null; вы должны сравнить с System.DBNull.Value:
object sqlDateTime = sqldatareader[0];
DateTime? dt = (sqlDateTime == System.DBNull.Value)
? (DateTime?)null
: Convert.ToDateTime(sqlDateTime);
В ответ на ваш комментарий тип данных Item
свойства DataReader
- это тип базового типа базы данных. Это может быть 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
, но ваш исходный вопрос не сказал нам об этом.
Для получения дополнительной информации об использовании DataReader
s обратитесь к MSDN.
Ответ 2
Недавно я нашел этот трюк, это просто:
DateTime? dt = sqldatareader[0] as DateTime?;
Ответ 3
Вам нужно проверить, является ли значение "DBNull", а не просто нулевым. В моем блоге я разместил небольшой вспомогательный класс: http://improve.dk/archive/2007/10/08/handling-dbnulls.aspx
Как только вы реализуете класс, вы используете его следующим образом:
DateTime? dt = DBConvert.To<datetime?>(sqldatareader[0]);
Ответ 4
Некоторое время назад я написал кучу методов расширения для DataRow, чтобы делать именно этот тип downcasting..., потому что я ненавижу писать повторяющиеся drivel. Использование прост:
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
}
Ответ 5
DateTime? dt = null;
if (sqldatareader[0] != System.DbNull.Value)
{
dt = (DateTime)sqldatareader[0];
}
Ответ 6
Просто используйте:
System.Nullable<System.DateTime> yourVariableName;
Упростите себя:)
Ответ 7
как насчет создания вспомогательного метода
private static DateTime? MyDateConverter(object o)
{
return (o == DBNull.Value || o == null) ? (DateTime?)null : Convert.ToDateTime(o);
}
Использование
MyDateConverter(sqldatareader[0])