Нулевой безопасный способ получить значения из IDataReader - PullRequest
12 голосов
/ 09 апреля 2010

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

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

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

Сейчас я делаю что-то подобное ..

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

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

Ответы [ 5 ]

22 голосов
/ 09 апреля 2010

Вот пара методов расширения, которые приятно закроют все ваши проблемы, связанные с извлечением строго типизированных значений из устройства чтения данных. Если значение равно DbNull, будет возвращен тип по умолчанию. В случае string, который является классом, будет возвращено null. Если поле было int, то будет возвращено 0. Кроме того, если вы ожидаете 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);

Extension

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

3 голосов
/ 19 июля 2015

Аналогично ответу @ 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));
}
2 голосов
/ 15 марта 2016

Комбинируя лучшие решения и предложения, вот C # 6 выражение стрелки версия с поддержкой 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));
}
2 голосов
/ 02 апреля 2011

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

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

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

0 голосов
/ 09 апреля 2010

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

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