What is the suggested approach or best practice for handling exceptions in tiered applications?
try/catch
blocks? Consider a simple example. Suppose you have a UI, that calls a business layer, that calls a data layer:
//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);
}
}
What criticisms would you make of the above exception handling?
thanks
My rule of thumb is generally to catch exceptions at the top level and log (or otherwise report) them there, because this is where you have the most information about the the error - most importantly the full stack trace.
There may be some reasons to catch exceptions in other tiers, however:
SqlException
wouldn't tell you.DatabaseUnavailableException
. The BL may ignore this for operations that are not critical or it may let it propogate for those that are. If the BL caught SqlException
instead it would be exposed to the implementation details of the DAL. Instead the possibility of throwing DatabaseUnavailableException
is part of the interface of the DAL.Logging the same error at multiple tiers is generally not useful, but I can think of one exception: when a lower tier doesn't know whether a problem is critical or not it can log it as a warning. If a higher tier decides that it is critical it can then log the same problem as an error.