2011-05-23 47 views
27

對象不能從DBNull轉換爲其他類型。對象無法從DBNull轉換爲其他類型

我有一個以下函數拋出上述錯誤。我正在處理商店程序和C#代碼中的所有空值。

那麼它在哪裏得到這個錯誤?

我可以看到catch塊中的錯誤。但我不明白哪一行在下面的create()獲取錯誤。

public Boolean Create(DataTO DataTO) 
{ 
    IDbTrans transaction = null; 
    IDbCmd IDbCmd; 

    string EncryptedPassword = Encrypt(DataTO.txtPwd); 
    Base dataAccCom = null; 

    try 
    { 
     dataAccCom = Factory.Create(); 
     dataAccCom.OpenConnection(); 
     transaction = dataAccCom.BeginTransaction(); 
     IDbCmd = dataAccCom.CreateCommand("sp_Register", true); 
     dataAccCom.AddParameter(IDbCmd, "op_Id", DbType.Int64, 0, ParameterDirection.Output); 
     dataAccCom.AddParameter(IDbCmd, "p_dlstTitle", DbType.String, ReplaceNull(DataTO.dlstTitle)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtFirstName", DbType.String, ReplaceNull(DataTO.txtFirstName)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtMiddleName", DbType.String, ReplaceNull(DataTO.txtMiddleName)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtLastName", DbType.String, ReplaceNull(DataTO.txtLastName)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtDob", DbType.DateTime, DataTO.txtDob); 
     dataAccCom.AddParameter(IDbCmd, "p_txtDesig", DbType.String, ReplaceNull(DataTO.txtDesig)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtOFlatNo", DbType.String, ReplaceNull(DataTO.txtOFlatNo)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtOBuild", DbType.String, ReplaceNull(DataTO.txtOBuild)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtOPost", DbType.String, ReplaceNull(DataTO.txtOPost)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtOArea", DbType.String, ReplaceNull(DataTO.txtOArea)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtOCity", DbType.String, ReplaceNull(DataTO.txtOCity)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtRBuild", DbType.String, ReplaceNull(DataTO.txtRBuild)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtRPost", DbType.String, ReplaceNull(DataTO.txtRPost)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtUserID", DbType.String,ReplaceNull(DataTO.txtUserID)); 
     dataAccCom.AddParameter(IDbCmd, "p_txtPwd", DbType.String, ReplaceNull(EncryptedPassword)); 
     dataAccCom.ExecuteNonQuery(IDbCmd); 
     DataTO.Id = Convert.ToInt64(dataAccCom.GetParameterValue(IDbCmd, "op_Id")); 
     transaction.Commit(); 
     return true; 



    } 
    catch (System.Exception ex) 
    { 
     if (transaction != null) 
     { 
      transaction.Rollback(); 
     } 
     throw ex; 
    } 
    finally 
    { 
     transaction = null; 
     if (dataAccCom != null) 
     { 
      dataAccCom.CloseConnection(); 
     } 
     dataAccCom = null; 
     IDbCmd = null; 
    } 
} 

public string ReplaceNull(string value) 
{ 
    if (value == null) 
    { 
     return ""; 
    } 
    else 
    { 
     return value; 
    } 
} 

public DateTime ReplaceNull(DateTime value) 
{ 
    if (value == null) 
    { 
     return DateTime.Now; 
    } 
    else 
    { 
     return value; 
    } 
} 

public double ReplaceNull(double value) 
{ 
    if (value == null) 
    { 
     return 0.0; 
    } 
    else 
    { 
     return value; 
    } 
} 
+0

注意在'double'和'DateTime'是毫無價值的,你的'ReplaceNull'重載。這些類型的值不能爲空,因此也不會傳遞'if(value == null)'條件。 – 2011-05-23 14:35:04

+0

除非它們當然是可空的,但那是另一回事。 – BoltClock 2011-05-23 14:36:07

+0

你有沒有采取這種方法?在Visual Studio中,考慮打破所有異常(Ctrl + Alt + E)並查看實際導致問題的線。 – 2011-05-23 14:36:35

回答

35

我在想你的輸出參數會返回一個DBNull值。添加一張支票,像這樣

var outputParam = dataAccCom.GetParameterValue(IDbCmd, "op_Id"); 
if(!(outputParam is DBNull)) 
    DataTO.Id = Convert.ToInt64(outputParam); 
+6

也許更好'Convert.IsDBNull()'? – abatishchev 2011-05-23 14:50:27

13

我懷疑該行

DataTO.Id = Convert.ToInt64(dataAccCom.GetParameterValue(IDbCmd, "op_Id")); 

引起的問題。存儲過程是否有可能將op_Id值設置爲null?

要警惕它,請使用Convert.IsDBNull方法。例如:

if (!Convert.IsDBNull(dataAccCom.GetParameterValue(IDbCmd, "op_Id")) 
{ 
DataTO.Id = Convert.ToInt64(dataAccCom.GetParameterValue(IDbCmd, "op_Id")); 
} 
else 
{ 
DataTO.Id = ...some default value or perform some error case management 
} 
2

您需要檢查DBNull,不null。此外,您的三個ReplaceNull方法中的兩個沒有意義。 doubleDateTime都是非空的,因此檢查他們null永遠是false ...

1

的TryParse通常是處理這種類型的東西最優雅的方式:

long temp = 0; 
if (Int64.TryParse(dataAccCom.GetParameterValue(IDbCmd, "op_Id").ToString(), out temp)) 
{ 
    DataTO.Id = temp; 
}  
1

原因的錯誤:在面向對象的編程語言中,null表示缺少對對象的引用。 DBNull表示未初始化的變體或不存在的數據庫列。來源:MSDN

我面對錯誤的實際代碼:

前更改了代碼:

if(ds.Tables[0].Rows[0][0] == null) // Which is not working 

    { 
      seqno = 1; 
     } 
    else 
    { 
      seqno = Convert.ToInt16(ds.Tables[0].Rows[0][0]) + 1; 
    } 

改變了代碼後:

if(ds.Tables[0].Rows[0][0] == DBNull.Value) //which is working properly 
     { 
        seqno = 1; 
     } 
      else 
      { 
        seqno = Convert.ToInt16(ds.Tables[0].Rows[0][0]) + 1; 
      } 

結論:當數據庫值返回null值,我們推薦使用DBNull類而不是像在C#語言中那樣指定爲null。

0

對於其他人來說,這個頁面上到達從谷歌:

的DataRow也有一個功能.IsNull("ColumnName")

public DateTime? TestDt; 
    public Parse(DataRow row) 
    { 
     if (!row.IsNull("TEST_DT")) 
      TestDt = Convert.ToDateTime(row["TEST_DT"]); 
    } 
相關問題