2011-03-23 87 views
7

我试图运行下面的代码,但得到一个转换错误。 如何重写我的代码以实现相同?将datareader值强制转换为一个可为空的变量

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

感谢

+0

是否知道dataReader [“BOOL_FLAG”]和dataReader [“INT_VALUE”]中包含的实际值是什么? – Jonas 2011-03-23 18:36:22

回答

12

使用的数据读取器的 “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"] 
+0

这是行不通的,你需要将'null'强制转换为'bool?' – 2011-03-23 18:40:12

+0

你说得对,我更新了我的答案......我忘了它不能告诉如果null是一个字符串,布尔?,MyCustomObject或什么 – taylonr 2011-03-23 21:08:34

+2

你可以简单地做'?(布尔?)null:(布尔)dataReader [“Bool_Flag”]' – 2011-03-24 08:35:48

2
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; 
} 
+0

'==假'? 'if(!...' – 2011-03-23 18:40:56

+0

只是我的约定 – 2011-03-23 18:42:06

8

考虑的功能做这件事。

这里的东西我在过去使用(可以让这个.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

我喜欢第二种扩展方法。但是,由于'IsDBNull()'只需要一个'int',所以我们必须调用类似于'dataReader.IsDBNull(dataReader.GetOrdinal(columnName))' – 2011-08-18 15:22:19

1

我敢肯定,我发现这个地方围绕interweb的灵感,但我似乎无法找到原始的来源了。不管怎样,下面你找到一个实用工具类,允许对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

辉煌。谢谢。 – 2014-03-18 14:13:11

0

记住,为DBNull是不一样的东西为空,所以你不能从一个转换为另一个。正如另一张海报所说,您可以使用IsDBNull()方法检查DBNull。

-2

尝试this版本。它执行一些基本的转换并管理默认值。

+1

虽然这可能会在理论上回答这个问题,[这将是更可取的](http://meta.stackexcha nge.com/q/8259)包括答案的基本部分,并提供参考链接。 – 2012-08-28 09:47:21

2

这里有可能有帮助的答案: https://stackoverflow.com/a/3308515/1255900

您可以使用“为”关键字。请注意评论中提到的警告。

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

或者,如果你不使用nullables,在你原来的职位:

boolResult = (dataReader["BOOL_FLAG"] as bool?) ?? 0; 
+0

我试图dataReader [“long_col”]长?对于一个可为空的长整型,但它在所有情况下都将该值设置为null。 – bpeikes 2014-10-01 13:28:40

1

这是我拍的扩展方法。列名的语义,并返回到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是参考类型,但它仍然无法从DBNull转换为nullint?也是如此。

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; 
} 
相关问题