2015-04-27 2 views
4

В this SO post я нашел общий метод расширения, который возвращает значение по умолчанию, если значение, считанное с помощью SqlDataReader является null или DBNull.Value, и правильно преобразовано значение в противном случае. Я реализовал это следующим образом:распаковка -1 и литье до NULLABLE <int> с использованием обобщенных типов дает InvalidCastException

public static T GetValueOrDefault<T>(this SqlDataReader reader, string columnName, T defaultValue = default(T)) 
{ 
    object val = reader[columnName]; 
    if (val == null || val == DBNull.Value) 
    { 
    return defaultValue; 
    } 

    return (T)val; 
} 

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

Однако, я прочитал обнуляемый int столбца из базы данных, как это:

MyProperty = reader.GetValueOrDefault<int?>("SomeColumnName") 

где режим отладки показывает мне, что val является -1 и T является int?, но я получаю InvalidCastException. От this post Я понял, что это невозможно, потому что unboxing и casting не могут быть выполнены за одну операцию (val имеет тип object, содержащий значение short), но что я могу сделать, чтобы он работал в моем случае? Поскольку это общий метод, я не знаю, как вручную распаковать его перед выполнением преобразования.

+0

MyProperty = reader.GetValueOrDefault («SomeColumnName») –

+0

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

+1

@InvisiblePanda № Что такое тип столбца базы данных? Если база данных может содержать большое значение, она не будет иметь тип 'short' в' SqlDataReader' –

ответ

5

Для получения действительно хорошего ответа вам необходимо разместить сообщение a good, minimal, complete code example.

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

При этом класс Convert намного сложнее об конверсиях; литой потребует точных матча, т.е. коробочного значения должно быть int (буквальный -1 бы int, но в вашем случае значения прихода от того, кто знает куда и легко может быть short или long или что-то).

Таким образом, вместо передачи, вызов, например. до Convert.ToInt32() будет работать лучше.

В вашем случае, с общим способом (т.е. тип неизвестен во время компиляции), метод Convert.ChangeType(), вероятно, более уместно:

public static T GetValueOrDefault<T>(this SqlDataReader reader, string columnName, T defaultValue = default(T)) 
{ 
    object val = reader[columnName]; 
    if (val == null || val == DBNull.Value) 
    { 
    return defaultValue; 
    } 

    return (T)Convert.ChangeType(val, typeof(T)); 
} 
+3

Хороший ответ, но я не думаю, что '-1' может быть' uint'. :) – hvd

+0

Эй, Питер, спасибо за ответ. Я действительно пытался создать такой пример, но я не мог воспроизвести проблему, потому что я не понимал ее достаточно хорошо:/То есть, я попытался воспроизвести ее, выполнив такие вещи, как '(int?) ((Short) -1) 'и тому подобное, но так и не получило вышеуказанную ошибку. Теперь, прочитав приведенные выше комментарии, я мог бы это сделать. – InvisiblePanda

+0

@ hvd: да, хорошая точка. :) –

Смежные вопросы