Обрабатывать DBNull в C # - PullRequest
       53

Обрабатывать DBNull в C #

37 голосов
/ 12 марта 2010

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

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

Ответы [ 13 ]

58 голосов
/ 12 марта 2010

Самый короткий (ИМХО) это:

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

Пояснение:

  • Если reader ["StockValue"] имеет тип int , значение будет возвращено, и "??" оператор вернет результат
  • Если читатель ["StockValue"] НЕ имеет типа int (например, DBNull), будет возвращено значение NULL, и "??" Оператор вернет значение 0 (ноль).
28 голосов
/ 12 марта 2010

То, как я справляюсь, это

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

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

int stockvalue = (reader["StockValue"] as int?).GetValueOrDefault(-1);
11 голосов
/ 12 марта 2010

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

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);
    }
}
10 голосов
/ 12 марта 2010
int? stockvalue = (int?)(!Convert.IsDBNull(result) ? result : null);

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

6 голосов
/ 12 марта 2010

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

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

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

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

6 голосов
/ 12 марта 2010

Да, вы можете использовать int? Таким образом, вы можете иметь значение по умолчанию, равное нулю, а не 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.
}
3 голосов
/ 31 мая 2010
int stockvalue = reader["StockValue"] != DbNull.Value ? Convert.ToInt32(reader["StockValue"]) : 0;
1 голос
/ 12 марта 2010

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

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

1 голос
/ 12 марта 2010

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

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

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

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

Дайте нам знать, какой способ работает для вас

0 голосов
/ 12 марта 2010
int? stockValue = reader["StockValue"] == null || reader["StockValue"] == DBNull.Value ? null : (int?)reader["StockValue"];
...