2010-04-09 27 views
10

(LocalVariable)ABC.string(Name)=(Idatareader)datareader.GetString(0);Null安全地從IDataReader獲取值

此名稱值來自數據庫.. 這裏發生了什麼,如果這個名稱值爲空,而閱讀它拋出異常?

我手動做一些條件如果這裏。我不想寫一個手動狀態來檢查我的所有變量..

我做這樣的事情現在..

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

是有什麼樣我們就可以編寫擴展方法呢? 感謝

回答

20

這裏是一對夫婦的擴展方法,這將很好地包裹起來你所有的顧慮周圍從數據讀取器檢索強類型的值。如果該值爲DbNull,則將返回該類型的默認值。如果是string這是一個班級,則會返回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

+0

如果值爲DBNull並且我們期待int,那麼返回0不是不好嗎?我們不應該在這種情況下拋出異常,因爲某些顯然是錯誤的 - 我們要麼期待int?或查詢產生錯誤的值類型?把0放在沒有實際價值的地方在一些特定的情況下可能是可以的,但是在一些常用的庫中有這個可能會導致一個非常微妙的錯誤,我想。 – poke 2014-02-28 14:44:48

+0

能夠傳遞一個默認值作爲參數很方便:'public static T GetValueOrDefault (this IDataRecord row,int ordinal,T defaultValue = default(T))' – mistika 2014-10-08 00:47:09

+0

@poke for int的情況下,你想有T 'int?'所以返回值可以爲null。 – 2015-07-19 20:56:33

0

我會使用這樣的:

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

它會做什麼?你能解釋一下嗎,謝謝 – kumar 2010-04-09 18:52:12

+0

「??運算符被稱爲空合併運算符,用於爲可爲空的值類型以及引用類型定義默認值,如果它不爲空,則返回左邊的操作數。否則它返回右操作數。「 http://msdn.microsoft。com/en-us/library/ms173224.aspx – Powerlord 2010-04-09 19:34:09

+2

您是否測試了這個,因爲DbNull!= null' – 2010-04-09 19:38:44

2

我的解決辦法是:

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

時,Status = GetValue<string>(currentDataRow["status"])

+4

而不是使用typeof()和GetType()你不能這樣做:「if(o是DBNull)」。在我看來,它更具可讀性。 – JMS10 2012-04-04 15:47:46

+2

'if(o == DBNull.Value)'有什麼問題? – 2014-04-28 22:10:36

+0

機會是'o == DBNull.Value'比'o是DBNull'更快,並且肯定比'typeof(DBNull)!= o.GetType()'快。 – nawfal 2017-12-01 12:15:27

3

類似@天空·桑德斯的答案,但有轉換不太嚴格:

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)); 
} 
1

結合頂級解決方案和建議,這裏是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)); 
}