Обработайте DBNull в C#

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

int stockvalue = 0;
if (!Convert.IsDBNull(reader["StockValue"]))
    stockvalue = (int)reader["StockValue"];
38
задан John Saunders 12 March 2010 в 14:25
поделиться

13 ответов

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

    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));
0
ответ дан 27 November 2019 в 03:04
поделиться

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

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

Объяснение:

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

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

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);
    }
}
11
ответ дан 27 November 2019 в 03:04
поделиться

Да, вы можете использовать int? Таким образом вы можете иметь значение по умолчанию null вместо 0. Поскольку результат stockvalue потенциально может быть 0, нет путаницы относительно того, была ли база данных 0 или нулевая. Например, как это (предварительно обнуляемое), у нас была инициализация по умолчанию -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.
}
7
ответ дан 27 November 2019 в 03:04
поделиться
int? stockvalue = (int?)(!Convert.IsDBNull(result) ? result : null);

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

10
ответ дан 27 November 2019 в 03:04
поделиться

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

0
ответ дан 27 November 2019 в 03:04
поделиться

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

Вместо этого в своем коде сделайте что-нибудь вроде этого:

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

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

6
ответ дан 27 November 2019 в 03:04
поделиться

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

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

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

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

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

1
ответ дан 27 November 2019 в 03:04
поделиться

Вы можете выполнить это преобразование прямо в запросе к базе данных, тем самым полностью исключив особый случай.

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

1
ответ дан 27 November 2019 в 03:04
поделиться
int? stockValue = reader["StockValue"] == null || reader["StockValue"] == DBNull.Value ? null : (int?)reader["StockValue"];
0
ответ дан 27 November 2019 в 03:04
поделиться

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

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

И назвать это так:

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

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

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

0
ответ дан 27 November 2019 в 03:04
поделиться

Я обращаюсь с этим так:

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

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

int stockvalue = (reader["StockValue"] as int?).GetValueOrDefault(-1);
28
ответ дан 27 November 2019 в 03:04
поделиться
int stockvalue = reader["StockValue"] != DbNull.Value ? Convert.ToInt32(reader["StockValue"]) : 0;
3
ответ дан 27 November 2019 в 03:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: