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

Обработать DBNull в С#

Есть ли лучший/более чистый способ сделать это?

int stockvalue = 0;
if (!Convert.IsDBNull(reader["StockValue"]))
    stockvalue = (int)reader["StockValue"];
4b9b3361

Ответ 1

Самый короткий (IMHO):

int stockvalue = (reader["StockValue"] as int?) ?? 0;

Пояснение:

  • Если reader [ "StockValue" ] имеет тип int, значение будет возвращено, а значение "??" оператор вернет результат
  • Если reader [ "StockValue" ] НЕ имеет тип int (например, DBNull), возвращается null, а символ "??" оператор вернет значение 0 (ноль).

Ответ 2

Как я справляюсь с этим,

int? stockvalue = reader["StockValue"] as int?;

Очень простая, чистая и одна строка. Если по какой-то причине я абсолютно не могу иметь нулевое значение (которое обычно я нахожу в непринужденной аргументации, так как я предпочел бы знать, имеет ли значение значение или был ли он унифицирован для примитивного типа), я бы сделал:

int stockvalue = (reader["StockValue"] as int?).GetValueOrDefault(-1);

Ответ 3

int? stockvalue = (int?)(!Convert.IsDBNull(result) ? result : null);

Одно из возможных решений, позволяющее гарантировать, что DBNull переносится на ваш код. Для нашей группы, как наилучшей практики, мы стараемся и не допускаем столбцы NULL в базе данных, если она действительно не нужна. Для кодирования требуется больше накладных расходов, и иногда просто переосмысление проблемы делает ее не требуемой.

Ответ 4

Я написал метод расширения несколько дней назад. Используя его, вы можете просто сделать:

int? stockvalue = reader.GetValue<int?>("StockValue");

Здесь используется метод расширения (в зависимости от ваших потребностей):

public static class ReaderHelper
{
    public static bool IsNullableType(Type valueType)
    {
        return (valueType.IsGenericType &&
            valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
    }

    public static T GetValue<T>(this IDataReader reader, string columnName)
    {
        object value = reader[columnName];
        Type valueType = typeof(T);
        if (value != DBNull.Value)
        {
            if (!IsNullableType(valueType))
            {
                return (T)Convert.ChangeType(value, valueType);
            }
            else
            {
                NullableConverter nc = new NullableConverter(valueType);
                return (T)Convert.ChangeType(value, nc.UnderlyingType);
            }
        }
        return default(T);
    }
}

Ответ 5

Да, вы можете использовать int? Таким образом, вы можете иметь значение по умолчанию null вместо 0. Так как результат запаса может потенциально равняться 0, не возникает путаницы в отношении того, была ли база данных 0 или нулевой. Например, как это (pre nullable), мы имели инициализацию по умолчанию -1, чтобы представить, что значение не было назначено. Лично я думал, что это было немного опасно, потому что, если вы забудете установить его на -1, проблема с повреждением данных может быть очень трудно отследить.

http://msdn.microsoft.com/en-us/library/2cf62fcy(VS.80).aspx

int? stockvalue = null;

if (!Convert.IsDBNull(reader["StockValue"]))
    stockvalue = (int)reader["StockValue"];

//Then you can check 

if(stockValue.HasValue)
{
  // do something here.
}

Ответ 6

В то время как удобно ссылаться на reader["StockValue"], это не очень эффективно. Он также не сильно типизирован, так как он возвращает тип object.

Вместо этого в вашем коде сделайте что-то вроде этого:

int stockValueOrdinal = reader.GetOrdinal("StockValue");
int? stockValue = reader.IsDbNull(stockValueOrdinal) ?
    null : 
    reader.GetInt32(stockValueOrdinal);

Конечно, лучше всего получить все ординалы за один раз, а затем использовать их во всем коде.

Ответ 7

int stockvalue = reader["StockValue"] != DbNull.Value ? Convert.ToInt32(reader["StockValue"]) : 0;

Ответ 8

Вот один из способов.

int stockvalue = Convert.IsDbNull(reader["StockValue"]) ? 0 : (int)reader["StockValue"];

Вы также можете использовать TryParse

int stockvalue = 0
Int32.TryParse(reader["StockValue"].ToString(), out stockvalue);

Сообщите нам, какой способ работает для вас

Ответ 9

Вы можете сделать это преобразование непосредственно в своем DB-запросе, тем самым избегая особого случая alltogether.

Но я бы не назвал это "чище", если вы не можете последовательно использовать эту форму в своем коде, так как вы потеряете информацию, вернув "0" вместо NULL из базы данных.

Ответ 10

используйте тип Nullable<int>... int? для краткости

Ответ 11

Не совсем. Вы можете инкапсулировать его в метод:

public int getDBIntValue(object value, int defaultValue) {
  if (!Convert.IsDBNull(value)) {
    return (int)value;
  }
  else {
    return defaultValue;
  }

И назовите его следующим образом:

stockVaue = getDBIntVaue(reader["StockValue"], 0);

Или вы можете использовать coalesce в своем запросе, чтобы вернуть возвращаемое значение не равным нулю.

Изменить - исправлены ошибки немого кода на основе полученных комментариев.

Ответ 12

В моем проекте есть два следующих метода расширения:

    public static T GetValueSafe<T>(this IDataReader dataReader, string columnName, Func<IDataReader, int, T> valueExtractor)
        where T : class 
    {
        T value;
        if (dataReader.TryGetValueSafe(columnName, valueExtractor, out value))
        {
            return value;
        }

        return null;
    }

    public static bool TryGetValueSafe<T>(this IDataReader dataReader, string columnName, Func<IDataReader, int, T> valueExtractor, out T value)
    {
        int ordinal = dataReader.GetOrdinal(columnName);

        if (!dataReader.IsDBNull(ordinal))
        {
            // Get value.
            value = valueExtractor.Invoke(dataReader, ordinal);

            return true;
        }

        value = default(T);
        return false;
    }

Использование может быть таким:

string companyName = dataReader.GetValueSafe("CompanyName", (reader, ordinal) => reader.GetString(ordinal));

Ответ 13

int? stockValue = reader["StockValue"] == null || reader["StockValue"] == DBNull.Value ? null : (int?)reader["StockValue"];