Как вывести обнуляемый DateTime из базы данных - PullRequest
16 голосов
/ 29 февраля 2012

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

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

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

Ответы [ 7 ]

29 голосов
/ 24 марта 2012

Я недавно нашел этот трюк, все просто:

DateTime? dt = sqldatareader[0] as DateTime?;
27 голосов
/ 29 февраля 2012

SQL-ноль не совпадает с .NET-ноль;Вы должны сравнить с 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 голосов
/ 29 февраля 2012

Вам нужно проверить, является ли значение «DBNull», а не просто ноль.Я разместил небольшой вспомогательный класс в своем блоге: http://improve.dk/archive/2007/10/08/handling-dbnulls.aspx

Как только вы реализуете класс, вы используете его следующим образом:

DateTime? dt = DBConvert.To<datetime?>(sqldatareader[0]);
1 голос
/ 11 декабря 2017

как насчет создания вспомогательного метода

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

Использование

MyDateConverter(sqldatareader[0])
1 голос
/ 29 февраля 2012

Некоторое время назад я написал кучу методов расширения для DataRow, чтобы сделать именно этот вид уныния ... потому что я ненавижу писать повторяющиеся бесполезные действия. Использование простое:

foreach( DataRow dr in someDataTable )
{
  DateTime? dt = dr.CastAsDateTimeNullable( "lastUpdated" ) ;
  int       id = dr.CastAsInt( "transactionID" ) ;
  // etc.
}

Вот часть значений DateTime. Добавление реализации для других типов данных должно быть довольно тривиальным. Не было бы трудно сделать то же самое с DataReader, если бы он был так склонен.

Я пытался придумать обобщенные методы, но ограничения в способе создания обобщений усложняли или делали невозможным выполнение и все равно получали желаемое поведение (например, значения null вместо default(T) - получение по умолчанию значения для значений NULL в SQL, которые затруднили бы различие между 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

}
0 голосов
/ 23 января 2014

Просто используйте:

System.Nullable<System.DateTime> yourVariableName;

Облегчи себя :)

0 голосов
/ 29 февраля 2012
DateTime? dt = null;

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