2009-09-19 106 views
2

我使用的是asp.net,我一直在努力處理錯誤,如果有任何錯誤消息傳遞給用戶。例如,我有一個User類,UserManager類和一個Database類。 Imagina我想顯示所有的用戶,顯示我從UserManager調用方法GetAllUsers返回一個User對象列表。此方法創建一個數據庫對象並調用方法ExecuteQuery(字符串查詢)。編輯: 現在我的問題,想象在ExecuteQuery()方法出現問題(無法打開數據庫)。我想在打開數據庫連接時通知用戶出錯了。我該如何做到這一點,並以一種整潔的方式處理這個問題?編輯2:C#最佳實踐錯誤處理和傳遞錯誤消息

你會這樣做嗎?否則呢?

public class Database() 
{ 
    private string _Error; 

    // property error (only get) 

    private void Open() 
    { 
    try 
    { 
     // Open DB 
     // Fails because of error   
    } 
    catch(Exception ex) 
    { 
     _Error = ex.Message; 
    } 
    } 

    public DataSet ExecuteQuery(string query) 
    { 
     try 
     { 
     Open(); 

     // Execute query 

     // return dataset 
     } 
     catch(Exception ex) 
     { 
      _Error = ex.Message; 
      return null; 
     } 
    } 
} 

public class UserManager() 
{ 
    private string _Error; 

    // Get property for Error  

    public List<User> GetAllUsers() 
    { 
     Database db = new Database() 

     Dataset DS = db.ExecuteQuery("my query goes here"); 

     (if DS == null) 
     { 
     _Error = db.Error; 
     return null; 
     } 

    } 
} 

在用戶界面上點擊事件:

protected void onClick_event(args) 
{ 

    Usermanager userman = new UserManager(); 
    List<User> users = userman.GetAllUsers(); 

    if(users == null) 
    { 
    // make a error panel visible 
    pnlError.Visible = true; 
    lblError.Text = userman.Error 
    } 
} 

這是一個好辦法?

+1

IMO,你應該只捕獲特定的異常,而不是System.Exception。只捕捉你知道可能會發生的異常,並且你無法預防。其他任何你應該允許的東西都會冒出來。 – jlembke 2009-09-19 17:49:44

+0

我編輯了我的答案,下面有一些鏈接供您查看。 – jlembke 2009-09-19 17:54:38

+0

@jlenbke:你的意思是'冒泡'?以及如何實施? – Martijn 2009-09-21 09:42:26

回答

3

我想你錯過了正確的方式來做異常處理。在數據庫中存儲語言/語言環境相關的文本並不是一個好主意。這個錯誤在它執行的上下文中也可能沒有意義,方法的調用者知道預期的內容,但是從數據庫中檢索值的代碼並不知道代碼的「更高目標」!數據庫錯誤的描述也可能根本不會吸引用戶,因爲他們系統無法獲取用戶列表,就這些了。對於開發人員來說,瞭解究竟出了什麼問題非常重要。把這個可見的用戶也可能會顯示他們不希望他們看到的數據,如表名,密碼,數據庫用戶名,這取決於異常包含的內容(你無法控制)

所以現在如何處理它:

  1. 抓住,你處理它的例外,那就是在onClick_Event
  2. 登錄到一個文件的詳細信息,頁面僅哪些用戶應該看到
  3. 在您的代碼(數據庫爲EG)遵循這個原則:

    • 不要修改對象的狀態,直到明確表示沒有任何事情可以出錯來保持對象處於一致狀態。這意味着不會開始修改成員,那麼異常就會出現,您將不得不將它們全部重置爲finally塊中的先前狀態。
    • 開始你的操作並拋出一個異常的問題(不要在這裏捕獲它,毫無意義,你只需要存儲一條消息或者整個異常以備以後檢索!)
    • 成功時,將臨時變量複製到對象

這樣,你總是有一致的狀態和乾淨的代碼的對象。

2

要麼包裝在using語句中,要麼嘗試/終止以確保db連接處理完畢,因爲特定類型的異常可能會給您帶來麻煩。

這個free book by Karl Seguin有一個關於異常處理的章節,它應該讓你對事情很清楚。

冒泡根據你的風格在那裏可以處理它的UI異常。對於未處理的異常,如下所述,ELMAH非常有用。

+0

以及如何將錯誤傳遞給用戶? – Martijn 2009-09-19 07:26:03

+0

將異常冒泡到最外面的點,然後根據異常類型決定顯示用戶的UI的責任。除非您向拋出的異常添加更多信息,否則這是您應該捕獲該異常的第一個地方。但說實話,閱讀該書的這一章,很難孤立地回答這個問題,有太多的事情需要考慮。 – dove 2009-09-19 07:30:14

+0

我編輯了我的startpost。你的意思是這樣嗎? – Martijn 2009-09-19 08:21:06

3

這一切都取決於您在查詢執行時遇到的問題類型。這些問題可能是從沒有找到記錄到連接失敗的任何事情。如果問題是您可以測試的問題,而沒有記錄,您可以測試該問題,並向用戶顯示一條消息,指出沒有找到記錄。即使連接失敗,您也應該能夠測試並告訴用戶。

對於您無法測試的問題,取決於您正在編寫的應用程序的類型,您可能希望讓應用程序失敗並使用一些框架,如ELMAH日誌並報告錯誤。

嘗試這些鏈接它們來自我other post關於這個主題的更多信息

Code Analysis Team Blog

Martin Fowler - Fail Fast

MSDN on Exception Handling

Checked vs Unchecked Exceptions

此外,this excellent article最近發佈

1

如果您不想在catch中使用通常的try/catch和顯示錯誤div,那麼您可以使用Page.Error event來捕獲頁面上下文中的句柄錯誤。在那裏,你可以調用Server.GetLastError()來獲取最後拋出的異常,然後通過將它們引導到錯誤頁面或在頁面上顯示/隱藏錯誤元素來通知用戶出了問題。