Нулевой безопасный способ получения значений из IDataReader

(LocalVariable) ABC.string(Name) = (Idatareader) datareader.GetString(0);

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

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

Теперь я делаю что-то вроде этого.

string abc =  (Idatareader)datareader.GetValue(0);
if(abc = null)
    //assiging null
else
    assiging abc value

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

Ответ 1

Вот несколько методов расширения, которые будут приятно обертывать все ваши проблемы при извлечении строго типизированных значений из устройства чтения данных. Если значение равно DbNull, значение по умолчанию будет возвращено. В случае string, который является классом, возвращается a null. Если поле было int, то 0 будет возвращено. Кроме того, если вы ожидаете int?, скажем, из поля с нулевым int, возвращается null.

Конкретное использование для случая Кумара:

string abc = datareader.GetValueOrDefault<string>(0);

Общее использование

var name = GetValueOrDefault<string>(reader, "Name");

или

var name = reader.GetValueOrDefault<string>("Name");

или

var name = reader.GetValueOrDefault<string>(0);

Удлинитель

public static class NullSafeGetter
{
   public static T GetValueOrDefault<T>(this IDataRecord row, string fieldName)
   {
       int ordinal = row.GetOrdinal(fieldName);
       return row.GetValueOrDefault<T>(ordinal);
   }

   public static T GetValueOrDefault<T>(this IDataRecord row, int ordinal)
   {
       return (T)(row.IsDBNull(ordinal) ? default(T) : row.GetValue(ordinal));
   }
}

из http://skysanders.net/subtext/archive/2010/03/02/generic-nullsafe-idatarecord-field-getter.aspx

Ответ 2

Подобно @sky-sanders отвечают, но менее строгие с преобразованиями:

public static T Get<T>(this IDataRecord row, string fieldName)
{
    int ordinal = row.GetOrdinal(fieldName);
    return row.Get<T>(ordinal);
}

public static T Get<T>(this IDataRecord row, int ordinal)
{
    var value = row.IsDBNull(ordinal) ? default(T) : row.GetValue(ordinal);
    return (T)Convert.ChangeType(value, typeof(T));
}

Ответ 3

Мое решение таково:

private static T GetValue<T>(object o) {
    if (typeof(DBNull) != o.GetType()) {
        return (T) o;
    }
    return default(T);
}

Когда Status = GetValue<string>(currentDataRow["status"])

Ответ 4

Объединяя верхние решения и предложения, вот версия С# 6 arrow с поддержкой GetValue<T> и GetValueOrDefault<T> с дополнительными параметрами значения по умолчанию.

public static class DataRecordExtensions {
    /// <summary>
    /// Generically extracts a field value by name from any IDataRecord as specified type. Will throw if DNE.
    /// </summary>
    public static T GetValue<T>(this IDataRecord row, string fieldName)
        => row.GetValue<T>(row.GetOrdinal(fieldName));

    /// <summary>
    /// Generically extracts a field value by ordinal from any IDataRecord as specified type. Will throw if DNE.
    /// </summary>
    public static T GetValue<T>(this IDataRecord row, int ordinal)
        => (T)row.GetValue(ordinal);

    /// <summary>
    /// Generically extracts a field value by name from any IDataRecord as specified type. Will return default generic types value if DNE.
    /// </summary>
    public static T GetValueOrDefault<T>(this IDataRecord row, string fieldName, T defaultValue = default(T))
        => row.GetValueOrDefault<T>(row.GetOrdinal(fieldName), defaultValue);

    /// <summary>
    /// Generically extracts a field value by ordinal from any IDataRecord as specified type. Will return default generic types value if DNE.
    /// </summary>
    public static T GetValueOrDefault<T>(this IDataRecord row, int ordinal, T defaultValue = default(T))
        => (T)(row.IsDBNull(ordinal) ? defaultValue : row.GetValue(ordinal));
}

Ответ 5

Я бы использовал что-то вроде этого:

string abc = (IDataReader)datareader.GetValue(0) ?? "Default";