I have a 3 tier based web application. I want to use I am using try catch block in my business logic layer. Is it right to use try/catch block in business logic or I need to use it in my UI layer?
see my code for DAL.
Data Access Layer
#region Insert in to Logbook
public int Insert_LogBook(string Vehicle_Number, DateTime Vehicle_Booking_Date, TimeSpan Time_From, TimeSpan Time_To, int KM_Start, int KM_End, string Vehicle_Used_By, string Cost_Code, string Budget_Line, DateTime Entry_Date)
{
try
{
SqlCommand com = new SqlCommand("Insert_LogBook", con);
com.Parameters.Add("@Vehicle_Number", SqlDbType.NVarChar, 100).Value = Vehicle_Number;
com.Parameters.Add("@Vehicle_Booking_Date", SqlDbType.DateTime).Value = Vehicle_Booking_Date;
com.Parameters.Add("@Time_From", SqlDbType.Time).Value = Time_From;
com.Parameters.Add("@Time_To", SqlDbType.Time).Value = Time_To;
com.Parameters.Add("@KM_Start", SqlDbType.Int).Value = KM_Start;
com.Parameters.Add("@KM_End", SqlDbType.Int).Value = KM_End;
com.Parameters.Add("@Vehicle_Used_Byr", SqlDbType.VarChar, 100).Value = Vehicle_Used_By;
com.Parameters.Add("@Cost_Code", SqlDbType.NVarChar, 50).Value = Cost_Code;
com.Parameters.Add("@Budget_Line", SqlDbType.NVarChar, 50).Value = Budget_Line;
com.Parameters.Add("@Entry_Date", SqlDbType.DateTime).Value = Entry_Date;
con.Open();
int res = com.ExecuteNonQuery();
}
catch (Exception ex)
{
WebMsgBox.Show(ex.Message);
}
finally
{
con.Close();
con.Dispose();
}
return 1;
}
#endregion
So should I use it in my bal OR IN UI layer or my code is ok. because If I don't use try/catch in my UI layer it won't catch exception (if there is any) and shows the error page.
Exception handling and throwing is something which I see misunderstood all the time, by most developers I've worked with.
You can and should use try/catch/(finally) pretty much anywhere, but...
You use catch only when you know which exception(s) are likely to occur and can recover from them. You should rarely ever catch the base Exception type. Allow all other errors to bubble up and be found by a programmer/tester/user.
You may want to catch a base exception type if you are going to throw another exception and attach the original exception as the InnerException.
You shouldn't think twice or get lazy about about creating your own exception types. For example, you may want to write a DataAccessException and throw that with exceptions caught within the tier attached in the InnerException. This way your logging will log an exception type that shows more accurately where the error occurred and calling code can choose only to catch the DataAccessException and perform a retry or something.
You could also consider making DataAccessException abstract and subclassing more specific exceptions like SqlDataAccessException or SecurityDataAccessException.
As you appear to know, you use finally when you want to ensure some code is run in the event of an error, even if you don't catch and handle the exception itself. In situations where you must always release a resource, the try/finally becomes a standard pattern.
Also, when possible, put the try/catch around the most specific patch of code where you are able to handle the error, allowing coding bugs in the surrounding code to crash the app.
You may think, "How can I catch a specific exception if I don't yet know which exceptions will be thrown?" You should see them documented on the ExecuteNonSql method and this is why it is so important to document your own API/component with the exceptions that it throws. Use XML comments to do this and if shipping a public DLL, switch on the XML comment file generator.
This may seem like a lot to take in, but its not in practice. When you invest in logging and proper exception handling/throwing, you'll be able to resolve bugs in minutes, you'll feel like champ and you'll soon learn to get upset with everyone else's poor code :)
At this stage in your programming life, I strongly recommend reading Framework Design Guidelines by Cwalina and Abrams. It will help you make the right choices quickly about all these types of question and you'll find using your own code is as joyful as using Microsoft's APIs (mostly).
Luke
Adding a bit about messages. I use this sort of thing in the error message.
"Cannot {perform some function}. A {type of exception} occurred. {Offer remedial advice or common reasons for the error}. Please see {inner exception|further log entries}."
For example, in a component for auto saving state in an app:
...
catch(FileNotFoundException fnfe)
{
string m = String.Format("Cannot save changes. A FileNotFoundException occurred. Check the path '{0}' is valid, that your network is up, and any removable media is available. Please see inner exception.", path);
_log.Error(m, fnfe);
throw new StorageLifecycleException(m, fnfe);
}
It just depends, you may use try catch
blocks in both layers.
But the problem is not where you are using exception handling code; the problem is how you are using. In the example you have provided you are catching a generic exception
, you do not know whether it is SqlException, or any other exception.
In general,
catch only the exceptions you can handle (in the example catch SqlException
, not all the exceptions)
display a user friendly message (in your example simply displaying the error message makes no sense for user)
log the exception
handle the exception where it occurs; if it is a DAL related exception handle it in the DAL layer, if it is a UI related exception handle it in the UI layer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With