Подтвердить что ты не робот

Как получить значение NULL DateTime из базы данных

Моя база данных SQL Server содержит значения NULL-времени с нулевым значением. Как я могу преобразовать их в объект с нулевым значением DateTime в моем приложении на С#?

Это то, что я думаю, это будет выглядеть, но это не так:

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

Ответ 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])