2011-03-23 90 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; 
} 
相關問題