Обработка DateTime DBNull - PullRequest
       11

Обработка DateTime DBNull

8 голосов
/ 20 октября 2010

Я видел много-много версий этого на SO, но ни одна из них, похоже, не совсем подходит для моих нужд

Мои данные поступают из базы данных поставщиков, которая допускает нулевое значение для полей DateTime. Сначала я извлекаю свои данные в таблицу данных.

using (SqlCommand cmd = new SqlCommand(sb.ToString(), conn))
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
    da.Fill(dt);
}

Я преобразовываю таблицу данных в список <> для обработки.

var equipment = from i in dt.AsEnumerable()
    select new Equipment()
    {
        Id = i.Field<string>("ID"),
        BeginDate = i.Field<DateTime>("BeginDate"),
        EndDate = i.Field<DateTime>("EndDate"),
        EstimatedLife = i.Field<double>("EstimatedLife")
    }

Итак, как мне проверить DBNull в этом случае? Я пытался написать метод.

    public DateTime CheckDBNull(object dateTime)
    {
        if (dateTime == DBNull.Value)
            return DateTime.MinValue;
        else
            return (DateTime)dateTime;
    }

Ответы [ 6 ]

7 голосов
/ 20 октября 2010

Один из возможных вариантов - сохранить его как обнуляемую дату и синтаксис DateTime?

Вот ссылка на MSDN об использовании обнуляемых типов

7 голосов
/ 20 октября 2010

Используйте IsDBNull()

System.Convert.IsDBNull(value);

или если у вас есть SqlDataReader

reader.IsDBNull(ordinal);

И сделайте ваши свойства DateTime обнуляемымиDateTime?) и установите null в случае DBNull.Field<T>() автоматически сделает это.

2 голосов
/ 20 октября 2010

вот пример кода, который я использую для чтения Datetime

я уверен, что это могло бы быть написано лучше, но для меня это нормально работает

   public DateTime? ReadNullableDateTimefromReader(string field, IDataRecord data)
    {

        var a = data[field];
        if (a != DBNull.Value)
        {
            return Convert.ToDateTime(a);
        }
        return null;
    }

    public DateTime ReadDateTimefromReader(string field, IDataRecord data)
    {
        DateTime value;
        var valueAsString = data[field].ToString();
        try
        {
            value = DateTime.Parse(valueAsString);
        }
        catch (Exception)
        {
            throw new Exception("Cannot read Datetime from reader");
        }

        return value;
    }
1 голос
/ 04 марта 2019

Я написал общий метод расширения, который я использую во всех своих проектах:

public static object GetValueSafely<T>(this System.Data.DataTable dt, string ColumnName, int index)
{
    if (typeof(T) == typeof(int))
    {
        if (dt.Rows[index][ColumnName] != DBNull.Value)
            return dt.Rows[index][ColumnName];
        else
            return 0;
    }
    else if (typeof(T) == typeof(double))
    {
        if (dt.Rows[index][ColumnName] != DBNull.Value)
            return dt.Rows[index][ColumnName];
        else
            return 0;
    }
    else if (typeof(T) == typeof(decimal))
    {
        if (dt.Rows[index][ColumnName] != DBNull.Value)
            return dt.Rows[index][ColumnName];
        else
            return 0;
    }
    else if (typeof(T) == typeof(float))
    {
        if (dt.Rows[index][ColumnName] != DBNull.Value)
            return dt.Rows[index][ColumnName];
        else
            return 0;
    }
    else if (typeof(T) == typeof(string))
    {
        if (dt.Rows[index][ColumnName] != DBNull.Value)
            return dt.Rows[index][ColumnName];
        else
            return string.Empty;
    }
    else if (typeof(T) == typeof(byte))
    {
        if (dt.Rows[index][ColumnName] != DBNull.Value)
            return dt.Rows[index][ColumnName];
        else
            return 0;
    }
    else if (typeof(T) == typeof(DateTime))
    {
        if (dt.Rows[index][ColumnName] != DBNull.Value)
            return dt.Rows[index][ColumnName];
        else
            return DateTime.MinValue;
    }
    else if (typeof(T) == typeof(bool))
    {
        if (dt.Rows[index][ColumnName] != DBNull.Value)
            return dt.Rows[index][ColumnName];
        else
            return false;
    }
    if (dt.Rows[index][ColumnName] != DBNull.Value)
        return dt.Rows[index][ColumnName];
    else
        return null;
}

Пример использования:

private void Example()
{
    DataTable dt = GetDataFromDb() // get data from database...
    for (int i = 0; i < dt.Rows.Count; i++)
    {
        Console.WriteLine((DateTime)dt.GetValueSafely<DateTime>("SomeDateColumn", i));
        Console.WriteLine((int)dt.GetValueSafely<int>("SomeIntColumn", i));
        Console.WriteLine((string)dt.GetValueSafely<string>("SomeStringColumn", i));
    }
}
1 голос
/ 07 ноября 2017

Я обнаружил, что самый простой способ справиться с этим - преобразовать поле в тип данных с помощью ключевого слова «как». Это прекрасно работает для полей базы данных, которые могут быть нулевыми, и это хорошо и просто.

Вот более подробно об этом: Прямое приведение к оператору 'as'?

Пример:

    IDataRecord record = FromSomeSqlQuerySource;
    string nullableString;
    DateTime? nullableDateTime;

    nullableString = record["StringFromRecord"] as string;
    nullableDateTime = record["DateTimeFromRecord"] as DateTime?;
0 голосов
/ 19 ноября 2014

Вы должны использовать DataRow["ColumnName"] is DBNull для сравнения DateTime null.

например:.

 if(studentDataRow["JoinDate"] is DBNull) { // Do something here }
...