![](/img/trans.png)
[英]When Checkbox value is null. Program throws this error“ Object cannot be cast from DBNull to other types.”
[英]Object cannot be cast from DBNull to other types. Error when a null value is read by the Reader
int topID = 0;
string TopIDQuery = "Select TopID from tbl_Organisation where OrganisationID=@OrgID";
paramet[0] = new MySqlParameter("@OrgID", MySqlDbType.Int32);
paramet[0].Value = OrgID;
reader = server.ExecuteReader(CommandType.Text, TopIDQuery, paramet);
while (reader.Read())
{
topID = Convert.ToInt32(reader["TopID"]);
}
reader.Close();
我正在從表中讀取topID
,當TopID
為null時我想將topID
為0,但由於它為null,因此拋出錯誤,當topID
為null時如何處理此錯誤
將您的閱讀代碼更改為:
while (reader.Read())
{
if(reader.IsDBNull(reader.GetOrdinal("TopID")))
topID = 0;
else
topID = Convert.ToInt32(reader["TopID"]);
}
在嘗試轉換列之前,在閱讀器上調用IsDBNull()
以檢查列:
using (reader = server.ExecuteReader(CommandType.Text, TopIDQuery, paramet))
{
while (reader.Read())
{
var column = reader.GetOrdinal("TopID");
if (!reader.IsDBNull(column))
topID = Convert.ToInt32(reader[column]);
}
}
}
或者,與DBNull.Value
進行比較:
var value = reader["TopID"];
if (value != DBNull.Value)
{
topID = Convert.ToInt32(value);
}
使用測試:
int columnNr = reader.GetOrdinal("TopID");
if (!reader.IsDBNull(columnNr)) {
topID = reader.GetInt32(columnNr);
}
問題是你試圖用null設置int,而不是在read中。 如果您嘗試放入的值為null,則可以設置備用值:
topID = Convert.ToInt32(reader["TopID"]) ?? 0;
另一種方法是你可以通過初始化topID來使用可空整數,如下所示:
int? topID = 0
但是這樣做仍然需要在其他地方檢查null,以及其他一些必須處理的東西,所以我建議在我的第一個顯示的值集上使用雙重問號。
這是我們在任何注冊表單的頁面加載時自動生成來自ms訪問數據庫的任何id的代碼
void Number()
{
con.Open();
int id;
cmd = new OleDbCommand("select max(ID) from Entry", con);
string value = (cmd.ExecuteScalar().ToString());
string max;
if (value != null)
{
max = "0"+value;
id = Convert.ToInt32(max);
lblNumber.Text = "Acronym of Reg form like for Emp for Employee"
+ Convert.ToString((id + 1));
}
con.Close();
}
在閱讀器上使用通用擴展方法(參見類似的SO問題 )
topID = reader.GetFieldValueOrDefaultIfDBNull<Int32>("TopID");
在您的閱讀器類(MySql,Sql,Oracle等)上實現此擴展方法
public static T GetFieldValueOrDefaultIfDBNull<T>(this SqlDataReader reader, string indexName)
{
if (reader.IsDBNull(reader.GetOrdinal(indexName)))
{
return default(T); // returns the default value for the type
}
else
{
return reader.GetFieldValue<T>(reader.GetOrdinal(indexName));
}
}
在嘗試檢索之前,您需要檢查值是否為DBNull。 此外,我建議在Convert.ToInt32()
使用GetInt32()
,因為已經聲明GetInt32()
內部優化可能會改變比使用Convert.ToInt32()
更快的地方。 我很久以前就學到了這一點,並且沒有一篇參考文章可供您查看。 當我得知這個GetInt32()
在內部使用Convert.ToInt32()
while(reader.Read()) {
int TopIDIndex = reader.GetOrdinal("TopID");
topID = reader.IsDBNull(TopIDIndex)
? 0
: reader.GetInt32(TopIDIndex);
}
我喜歡使用DataTable
而不是DataReader
。 我討厭重復的樣板,所以我在DataRow
類中添加了一些擴展方法來封裝downcast邏輯並使代碼更具可讀性:
DataTable dt = ExecStoredProcedure() ;
foreach ( DataRow dr in dt )
{
int id = dr.CastAsInt("id") ;
dateTime? dtLastUpdated = dr.CastAsDateTimeNullable("last_update_date") ;
int? col3 = dr.CastASIntNullable(3) ;
}
這里是將一個列值從DataRow
向下轉換為int
/ int?
:
#region downcast to int
public static int CastAsInt( this DataRow row , int index )
{
return toInt( row[index] ) ;
}
public static int CastAsInt( this DataRow row , string columnName )
{
return toInt( row[columnName] ) ;
}
public static int? CastAsIntNullable( this DataRow row , int index )
{
return toIntNullable( row[index] );
}
public static int? CastAsIntNullable( this DataRow row , string columnName )
{
return toIntNullable( row[columnName] ) ;
}
#region conversion helpers
private static int toInt( object o )
{
int value = (int)o;
return value;
}
private static int? toIntNullable( object o )
{
bool hasValue = !( o is DBNull );
int? value = ( hasValue ? (int?) o : (int?) null ) ;
return value;
}
#endregion conversion helpers
#endregion downcast to int
我確定從DataReader掛起類似的擴展方法會相當簡單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.