fle*_*esh 31 c# exception-handling n-tier-architecture
在分层应用程序中处理异常的建议方法或最佳实践是什么?
try/catch积木? 考虑一个简单的例子.假设您有一个调用业务层的UI,它调用数据层:
//UI
protected void ButtonClick_GetObject(object sender, EventArgs e)
{
try {
MyObj obj = Business.GetObj();
}
catch (Exception ex) {
Logger.Log(ex); //should the logging happen here, or at source?
MessageBox.Show("An error occurred");
}
}
//Business
public MyObj GetObj()
{
//is this try/catch block redundant?
try {
MyObj obj = DAL.GetObj();
}
catch (Exception ex) {
throw new Exception("A DAL Exception occurred", ex);
}
}
//DAL
public MyObj GetObj()
{
//Or is this try/catch block redundant?
try {
//connect to database, get object
}
catch (SqlException ex) {
throw new Exception("A SQLException occurred", ex);
}
}
Run Code Online (Sandbox Code Playgroud)
您对上述异常处理有何批评?
谢谢
EMP*_*EMP 20
我的经验法则通常是在顶层捕获异常并在那里记录(或以其他方式报告),因为这是您获得有关错误的最多信息的地方 - 最重要的是完整的堆栈跟踪.
但是,可能有一些原因可以捕获其他层中的异常:
SqlException不会告诉您.DatabaseUnavailableException.对于不重要的操作,BL可能会忽略它,或者可能让它为那些操作传播.如果BL被捕获SqlException,则会暴露于DAL的实现细节.相反,投掷的可能性DatabaseUnavailableException是DAL界面的一部分.在多个层中记录相同的错误通常没有用,但我可以想到一个例外:当较低层不知道问题是否严重时,它可以将其记录为警告.如果更高层确定它是关键的,那么它可以将相同的问题记录为错误.
Flo*_*scu 11
以下是我遵循的与异常处理相关的一些规则:
Application.ThreadException应该实现该事件.在ASP .Net应用Application_Error程序中,应实现global.asax中的事件处理程序.这些位置是您可以在代码中捕获异常的最高位置.在许多应用程序中,这将是您将捕获大多数异常的地方,除了日志记录之外,您还可以在此处实现一个通用且友好的错误消息窗口,该窗口将呈现给用户. SqlConnection conn = null;
try
{
conn = new SqlConnection(connString);
...
}
// do not implement any catch in here. db exceptions logic should be implemented at upper levels
finally
{
// finalization code that should always be executed.
if(conn != null) conn.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
throw;.这将确保保留堆栈跟踪.使用throw ex;将重置堆栈跟踪. 首先要解决的问题是永远不要抛出将军Exception。
第二,除非确实有充分的理由来包装异常,否则只需在 catch 子句中使用throw;代替即可。throw new...
第三(这不是一个硬性规定),不要在 UI 层以下的任何点捕获一般异常。UI 层应该捕获一般异常,以便可以向最终用户显示用户友好的消息,而不是发生爆炸的技术细节。如果您在更深的层中捕获一般异常,则它可能会无意中被吞没,并导致很难追踪的错误。