如果你從事過 PPC 上的 .NET Compact Framework 1.0 和 SQL Server CE 2.0 的開發,應該已經跟 SqlCeException 交過手了。本文將向初學者介紹如何正確地捕獲和有效地處理 SqlCeException。
一、捕獲SqlCeException
在 .NET Compact Framework 1.0 中,SqlCeException 是一個需要特殊處理的異常類,如果你不對它進行單獨的捕獲,擷取到的異常資訊將是"SqlCeException"或者Null 字元串,而不是你想要擷取到的真實異常資訊。接下來我給大家分析幾段代碼:
[代碼1]
try
{
// 建立一個資料庫連接,連接字串中的資料庫是不存在的
SqlCeConnection conn = new SqlCeConnection("Data Source=nonExistSource.sdf;");
// 開啟資料庫連接,將拋出一個 SqlCeException
conn.Open();
}
catch (Exception ex)
{
// 擷取到的異常資訊是空白字串
MessageBox.Show(ex.Message);
}
[代碼1]中的異常處理代碼捕獲到的是一個 SqlCeException 的異常執行個體,在 catch 塊中沒有對該執行個體進行類型轉換,直接就擷取它的 Message 值,得到的錯誤資訊將是空白字串,並非原始的異常資訊。再看看[代碼2]:
[代碼2] try
{
// 建立一個資料庫連接,連接字串中的資料庫是不存在的
SqlCeConnection conn = new SqlCeConnection("Data Source=nonExistSource.sdf;");
// 開啟資料庫連接,將拋出一個 SqlCeException
conn.Open();
}
catch (SqlCeException ssex)
{
// 擷取到的異常資訊如下:
// "The database file cannot be found. Check the path to the database. [,,,File name,,]"
MessageBox.Show(ssex.Message);
}
catch (Exception ex)
{
// 擷取其他異常資訊
MessageBox.Show(ex.Message);
}
在[代碼2]中,我們對 SqlCeException 單獨捕獲,最後擷取到了原始的錯誤資訊"The database file cannot be found. Check the path to the database. [,,,File name,,]"。
二、處理SqlCeException
如果你有一個對異常進行統一處理的類和方法,如:ExceptionManager.Publish(Exception exception)。根據我上面的分析,你不得不在 Pulibsh 方法中對 SqlCeException 進行類型轉化。如[代碼3] 所示:
[代碼3]
StringBuilder sb = new StringBuilder();
sb.Append("Message: ");
if (exception is SqlCeException)
{
sb.Append(((SqlCeException)exception).Message);
}
else
{
sb.Append(exception.Message);
}
從 SqlCeException.Message 屬性擷取到的錯誤資訊往往是不夠詳細的,因為這些資訊是在 SQL Server CE 2.0 中預先定義好的。我們希望擷取到更加詳細的錯誤資訊,能夠指導我們迅速找到出錯代碼的具體位置。比如在[代碼2]中,我們想要知道找不到的資料庫檔案名稱是什麼。其實除了 Message 屬性外,從 SqlCeException 中還可以擷取到更多的錯誤資訊,請看[代碼4]:
[代碼4]
/// <summary>
/// 產生一個詳細錯誤訊息的 SqlCeException 例外處理常式。
/// </summary>
/// <param name="exception">SqlCeException 異常對象。</param>
public static void ShowErrors(SqlCeException exception)
{
// 擷取包含一個或多個 SqlCeError 對象的集合,這些對象包含有關
// SQL Server CE .NET Framework 精簡版資料提供者產生的異常的詳細資料。
SqlCeErrorCollection errs = exception.Errors;
// 擷取導致當前異常的 Exception 執行個體。
Exception inner = exception.InnerException;
if (null != inner)
{
// 顯示內部異常資訊。
MessageBox.Show("Inner Exception: " + inner.ToString());
}
StringBuilder sb = new StringBuilder();
// 用訊息框顯示每個錯誤的詳細資料
foreach (SqlCeError err in errs)
{
// 標識錯誤類型的 HRESULT 值,這些錯誤不是 SQL Server CE 固有的。
sb.Append("Error Code: ").Append(err.HResult.ToString("X"));
// 對錯誤進行描述的文本。
sb.Append("\nMessage : ").Append(err.Message);
// 擷取 SqlCeError 的本機錯誤號碼。
sb.Append("\nMinor Err.: ").Append(err.NativeError);
// 建置錯誤的提供者的名稱。
sb.Append("\nSource : ").Append(err.Source);
// 遍曆前三個錯誤參數。SQL Server CE 使用錯誤參數來提供有關錯誤的其他詳細資料。
foreach (int numPara in err.NumericErrorParameters)
{
// 雖然錯誤可能存在參數,但並非發生的所有錯誤都返回參數。
// 如果發生某個錯誤時沒有返回任何參數,則該數組的值為 0。
if (numPara != 0)
{
sb.Append("\nNum. Par. : ").Append(numPara);
}
}
// 遍曆最後三個錯誤參數。SQL Server CE 使用錯誤參數來提供有關錯誤的其他詳細資料。
foreach (string errPara in err.ErrorParameters)
{
// 雖然錯誤可能存在參數,但並非發生的所有錯誤都返回參數。
// 如果發生某個錯誤時沒有返回任何參數,則該數組的值將為空白字串。
if (errPara != String.Empty)
{
sb.Append("\nErr. Par. : ").Append(errPara);
}
}
MessageBox.Show(sb.ToString());
sb.Remove(0, sb.Length);
}
}
我們可以使用[代碼4]中的 ShowErrors 方法來處理[代碼2]中的 SqlCeException 異常。
[代碼5]
try
{
// 建立一個資料庫連接,連接字串中的資料庫是不存在的
SqlCeConnection conn = new SqlCeConnection("Data Source=nonExistSource.sdf;");
// 開啟資料庫連接,將拋出一個 SqlCeException
conn.Open();
}
catch (SqlCeException ssex)
{
// 擷取詳盡的異常資訊
ShowErrors(ssex);
}
catch (Exception ex)
{
// 擷取其他異常資訊
MessageBox.Show(ex.Message);
}
異常資訊的內容如所示:
三、總結
本文介紹的內容是我這段時間在項目開發中總結的經驗,希望對剛剛接觸 SQL Server CE 開發的人在處理 SqlCeException 上有協助。
範例程式碼
[參考]
SQL Server CE 2.0 Books Online: Error Handling in C#