如果我有類似下面的代碼:可能使用?? (合併運算符)與DBNull?
while(myDataReader.Read())
{
myObject.intVal = Convert.ToInt32(myDataReader["mycolumn"] ?? 0);
}
它引發錯誤:
Object cannot be cast from DBNull to other types.
定義intVal
爲可空int是不是一種選擇。有沒有辦法讓我做到這一點?
如果我有類似下面的代碼:可能使用?? (合併運算符)與DBNull?
while(myDataReader.Read())
{
myObject.intVal = Convert.ToInt32(myDataReader["mycolumn"] ?? 0);
}
它引發錯誤:
Object cannot be cast from DBNull to other types.
定義intVal
爲可空int是不是一種選擇。有沒有辦法讓我做到這一點?
你可以使用擴展方法? (註銷我的頭頂部)
public static class DataReaderExtensions
{
public static T Read<T>(this SqlDataReader reader, string column, T defaultValue = default(T))
{
var value = reader[column];
return (T)((DBNull.Value.Equals(value))
? defaultValue
: Convert.ChangeType(value, typeof(T)));
}
}
你會使用它像:
while(myDataReader.Read())
{
int i = myDataReader.Read<int>("mycolumn", 0);
}
我最終選擇了擴展方法路線。我遇到了'Convert.ChangeType ...'部分的錯誤,所以我做了一些小改動。 – 2012-02-24 20:24:50
你可以用你必須做的'小改動'來更新我的答案嗎? – 2012-02-24 20:30:03
其實我仍然有一些麻煩讓演員工作。 '轉換。ChangeType(reader [column],typeof(T))'不能編譯,所以我切換到這個引發運行時異常的'(T)reader [column]'。有任何想法嗎? – 2012-02-24 20:35:35
爲什麼不使用非空合併運算符以外的東西(DBNull.Value
= null
!):
你總是可以包起來,有着簡潔的擴展方法:
public static T Read<T>(this DataReader reader, string column, T defaultVal)
{
if(reader[column] == DBNull.Value) return defaultVal;
return Convert.ChangeType(reader[column], typeof(T));
}
不,僅適用於空值。
對象的擴展方法檢查DBNull,並返回一個默認值呢?
//may not compile or be syntactically correct! Just the general idea.
public static object DefaultIfDBNull(this object TheObject, object DefaultValue)
{
if(TheObject is DBNull)
return DefaultValue;
return TheObject;
}
如何像:
object x = DBNull.Value;
int y = (x as Int32?).GetValueOrDefault(); //This will be 0
或者你的情況:
int i = (myDataReader["mycolumn"] as Int32?).GetValueOrDefault();
正如John Saunders在他對「可能重複」問題的回答中指出的那樣,這種方法的缺點是如果列的數據類型發生變化,則無法引發異常。例如,如果「mycolumn」擁有42的「short」值,則變量「i」將具有值「0」。直接強制轉換會引發異常,提請注意代碼和數據庫之間的類型不匹配。 – phoog 2012-02-24 19:56:53
@phoog - 有效的點,我想每種方法都有其優點和缺點。就我個人而言,我喜歡我的數據庫和代碼儘可能緊密結合。我要麼在代碼中使用'int?',要麼在數據庫中不允許'null'。 – 2012-02-24 20:07:49
你能簡單地使用Int32.Tryparse
?
int number;
bool result = Int32.TryParse(myDataReader["mycolumn"].ToString(), out number);
按照MSDN,number
將包含0,如果轉換失敗
+1,很好的答案。這可能會奏效,但我實際上正試圖分配的int是一個對象屬性,它不適用於'out'。 – 2012-02-24 19:51:10
這不會編譯,是嗎?數據閱讀器索引器返回一個對象引用,TryParse接受一個字符串參數。當然,您可以在對象上調用ToString,但構造int的字符串表示的效率相當低,因此您可以解析它。拆箱轉換會更有效率。 – phoog 2012-02-24 19:53:14
@phoog,好點。如果它是空的ToString反正會彈。可以使用'as string'代替。 – 2012-02-24 19:55:47
這裏有一個選擇:在C#中處理的DBNull]的
while (myDataReader.Read())
{
myObject.intVal = (myDataReader["mycolumn"] as int? ?? 0);
}
絕對是最好的方式!謝謝Edyn。 – ClownCoder 2016-03-31 03:51:19
明智的答案!很乾淨。 – 2016-08-10 16:43:51
可能重複(HTTP://計算器.com/questions/2433155/handle-dbnull-in-c-sharp) – BoltClock 2012-02-24 19:32:47