приведение значения datareader к переменной Nullable - PullRequest
9 голосов
/ 23 марта 2011

Я пытаюсь запустить следующий код, но получаю ошибку приведения. Как я могу переписать свой код для достижения того же?

boolResult= (bool?)dataReader["BOOL_FLAG"] ?? true;
intResult= (int?)dataReader["INT_VALUE"] ?? 0;

Спасибо

Ответы [ 9 ]

14 голосов
/ 23 марта 2011

Используйте метод «IsDbNull» в считывателе данных ... например:

bool? result = dataReader.IsDbNull(dataReader["Bool_Flag"]) ? null : (bool)dataReader["Bool_Flag"]

Редактировать

Вам нужно сделать что-то похожее на: bool?nullBoolean = null;

у вас будет

bool? result = dataReader.IsDbNull(dataReader["Bool_Flag"]) ? nullBoolean : (bool)dataReader["Bool_Flag"]
10 голосов
/ 23 марта 2011

Рассмотрите возможность сделать это в функции.

Вот кое-что, что я использовал в прошлом (вы можете сделать это методом расширения в .net 4):

public static T GetValueOrDefault<T>(SqlDataReader dataReader, System.Enum columnIndex)
{
    int index = Convert.ToInt32(columnIndex);

    return !dataReader.IsDBNull(index) ? (T)dataReader.GetValue(index) : default(T);
}

Править

Как расширение (не проверено, но вы поняли идею) и использование имен столбцов вместо индекса:

public static T GetValueOrDefault<T>(this SqlDataReader dataReader, string columnName)
{

    return !dataReader.IsDBNull(dataReader[columnName]) ? (T)dataReader.GetValue(dataReader[columnName]) : default(T);
}

использование:

bool? flag = dataReader.GetValueOrDefault("BOOL_COLUMN");
3 голосов
/ 07 сентября 2012

Здесь есть ответ, который может быть полезен: https://stackoverflow.com/a/3308515/1255900

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

nullableBoolResult = dataReader["BOOL_FLAG"] as bool?;

Или, если вы не используете nullables, как в исходном сообщении:

boolResult = (dataReader["BOOL_FLAG"] as bool?) ?? 0;
2 голосов
/ 23 марта 2011
bool? boolResult = null;
int? intResult = null;

if (dataReader.IsDBNull(reader.GetOrdinal("BOOL_FLAG")) == false)
{
  boolResult  = dataReader.GetBoolean(reader.GetOrdinal("BOOL_FLAG"));
}
else
{
  boolResult = true;
}

if (dataReader.IsDBNull(reader.GetOrdinal("INT_VALUE")) == false)
{
   intResult= dataReader.GetInt32(reader.GetOrdinal("INT_VALUE"));
}
else
{
   intResult = 0;
}
1 голос
/ 15 февраля 2019

с использованием метода расширения:

public static T GetValueOrDefault <T> (this SqlDataReader reader, string column) {
    var isDbNull = reader[column] == DBNull.Value;
    return !isDbNull ? (T) reader[column] : default (T);
}
1 голос
/ 01 декабря 2016

Вот мой шанс на метод расширения.Семантика имени столбца и возвращается к default(T) при обнаружении нулевого значения.

public static class DbExtensions
{
    public static T ReadAs<T>(this IDataReader reader, string col)
    {
        object val = reader[col];
        if (val is DBNull)
        {
            // Use the default if the column is null
            return default(T);
        }
        return (T)val;
    }
}

Вот пример использования.Помните, что несмотря на то, что string является ссылочным типом, он все равно не сможет привести к null из DBNull.То же самое верно для int?.

public Facility Bind(IDataReader reader)
{
    var x = new Facility();
    x.ID = reader.ReadAs<Guid>("ID");
    x.Name = reader.ReadAs<string>("Name");
    x.Capacity = reader.ReadAs<int?>("Capacity");
    x.Description = reader.ReadAs<string>("Description");
    x.Address = reader.ReadAs<string>("Address");
    return x;
}
1 голос
/ 23 марта 2011

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

public static class DataReaderExtensions
{
    public static TResult Get<TResult>(this IDataReader reader, string name)
    {
        return reader.Get<TResult>(reader.GetOrdinal(name));
    }

    public static TResult Get<TResult>(this IDataReader reader, int c)
    {
        return ConvertTo<TResult>.From(reader[c]);
    }
 }

Использование:

  reader.Get<bool?>("columnname")

или

 reader.Get<int?>(5)

Вот включающий класс утилит:

public static class ConvertTo<T>
{
    // 'Factory method delegate', set in the static constructor
    public static readonly Func<object, T> From;

    static ConvertTo()
    {
        From = Create(typeof(T));
    }

    private static Func<object, T> Create(Type type)
    {
        if (!type.IsValueType) { return ConvertRefType; }
        if (type.IsNullableType())
        {
            return (Func<object, T>)Delegate.CreateDelegate(typeof(Func<object, T>), typeof(ConvertTo<T>).GetMethod("ConvertNullableValueType", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(new[] { type.GetGenericArguments()[0] }));
        }
        return ConvertValueType;
    }

    // ReSharper disable UnusedMember.Local
    // (used via reflection!)
    private static TElem? ConvertNullableValueType<TElem>(object value) where TElem : struct
    {
        if (DBNull.Value == value) { return null; }
        return (TElem)value;
    }
    // ReSharper restore UnusedMember.Local


    private static T ConvertRefType(object value)
    {
        if (DBNull.Value != value) { return (T)value; }
        return default(T);
    }

    private static T ConvertValueType(object value)
    {
        if (DBNull.Value == value)
        {
            throw new NullReferenceException("Value is DbNull");
        }
        return (T)value;
    }
}

РЕДАКТИРОВАТЬ: использует метод расширения IsNullableType (), определенный следующим образом:

    public static bool IsNullableType(this Type type)
    {
        return 
            (type.IsGenericType && !type.IsGenericTypeDefinition) && 
            (typeof (Nullable<>) == type.GetGenericTypeDefinition());
    }
0 голосов
/ 28 августа 2012

Попробуйте эту версию.Он выполняет некоторые основные преобразования и управляет значениями по умолчанию.

0 голосов
/ 23 марта 2011

Помните, что DBNull - это не то же самое, что null, поэтому вы не можете разыгрывать одно из другого.Как сказал другой автор, вы можете проверить DBNull с помощью метода IsDBNull ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...