How do I properly handle an error in a generic class? - c#

I am working on a generic class and am working on handling errors. I am using a try catch on one spot where I am getting an error. The question is, how do I return that error back to the calling method?
public static DataTable GetData(string connString, string sqlStatement, Action<iDB2ParameterCollection> parameters)
{
DataTable dt = new DataTable();
using (iDB2Connection conn = new iDB2Connection(connString))
{
using (iDB2Command cmd = new iDB2Command(sqlStatement, conn))
{
conn.Open();
if (parameters != null) { parameters(cmd.Parameters); }
try
{
using (iDB2DataAdapter da = new iDB2DataAdapter(cmd)) { da.Fill(dt); }
}
catch (iDB2SQLErrorException e)
{
}
conn.Close();
}
}
return dt;
}

By not catching it in a base class!
I am not a fan of capturing and swallowing exceptions at the base class level.
Let your derived classes worry about these details.
Side Note (Evidence of position):
You'll notice that in practically any API, the doucmentation will report what exceptions will be thrown with classes. If they were to catch them in a base class, they have effectively swallowed them rendering you helpless as the user of said classes.
Additional Articles:
...instead of writing our abstractions based on details, the we should
write the details based on abstractions.
This is a core tenant of Dependency Inversion Principle.
Take a look at this article for some really good things to consider in your design process, http://www.oodesign.com/design-principles.html

We do this, for the same reason you appear to be doing it. So that you can ensure the connection is closed.
We just re-throw the same error and lose the connection in the "finally" block. This lets the connection be closed and still bubble the connection back up to the caller, because the "finally" block gets executed regardless.
catch (iDB2SQLErrorException e)
{
throw e;
}
finally
{
cn.Close();
}
The above code is what we've used for years, but thanks to the comments, I think it might need tweaking. See this blog post for info on how to preserve the stack trace with exception handling: http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-preserving-the-full-call-stack-trace.aspx

You could implement some logic to handle to exception internally in this method and re-throw it again. The exception will bubble up in the call stack;
Other option is to use error codes to pass the error up in the stack. It depends on the API.

Either don't catch it and let the caller handle it, or throw your own error that wraps the original one:
class DataRetrievalException : Exception {
DataRetrievalException(String message, Exception cause) : base(message, cause) {}
}
// ...
catch (iDB2SQLErrorException e) {
throw new DataRetrievalException("Error retrieving data from database", e);
}

Related

How to be explicit about NOT throwing an exception?

This might be a broad question, but recently I ahve wondered about the following: In our C# backend we have many places that wrap some code in a try/catch block, specifically calls to external WcF services. Some of these calls are crucial for the application so in the catch block we log the error and rethrow, like:
catch(Exception ex)
{
_logger.Error("Some good error message");
throw ex;
}
On the other hand there are services we allow to fail, but we still want to log the error, so they look like:
catch(Exception ex)
{
_logger.Error("Some good error message");
}
Now reading the code of team members I can not be sure if they forgot to throw or if this is the intended behaviour.
Q: Is there a way, resp. what is the default way, to explicitly NOT rethrow (without including a comment in the code).
I have considered something like this:
catch(Exception ex)
{
_logger.Error("Some good error message");
NotThrowingHereOnPurpose();
}
// ...
// and further below a private method
// ...
private void NotThrowingHereOnPurpose(){}
One approach that may be useful here is to change the way of invoking the code that you explicitly allow to fail in such a way that it does not look like a try/catch block at all.
For example, you could write a helper method that does error reporting, and call it with actions expressed as lambdas:
void InvokeFailSafe(Action action, Action<Exception> onFailure = null) {
try {
action();
} catch (Exception e) {
if (onFailure != null) {
onFailure(e);
}
}
}
Now instead of try/catch you would write this:
InvokeFailSafe(
() => {
... The code that may fail
}
, exception => _logger.Error("Some good error message: {0}", exception)
);
or like this, if you don't want anything logged:
InvokeFailSafe(
() => {
... The code that may fail
}
);
If you code things this way, there would be no doubts about a missing throw statement.
It's an opposite solution to dasblinkenlight's answer. Instead of notifying others that the exception mustn't be rethrown it would say that it must be.
If you only want to log it then use the Error method as usual. Otherwise, you can write an extension method for your logger to log and throw exceptions.
The method would take the catched exception and rethrow it using the ExceptionDispatchInfo class. The ExceptionDispatchInfo is used to rethrow the exception with the original stack trace information and Watson information. It behaves like throw; (without the specified exception).
public static void ErrorAndThrow(this ILogger logger, string message, Exception exception)
{
var exceptionInfo = ExceptionDispatchInfo.Capture(exception);
logger.Error(message);
exceptionInfo.Throw();
}
And use it this way:
try
{
}
catch (Exception ex)
{
// ex would be rethrown here
_logger.ErrorAndThrow("Some good error message", ex);
}
Q: Is there a way, resp. what is the default way, to explicitly NOT
rethrow (without including a comment in the code).
Ideal way would be not to catch a generic exception. Now, to throw or not that entirely depends on your case. You need to understand that Exception handling is used when you know what to do in case an exception occurs. So, only specific exceptions should be handled. Catching exceptions without knowing what you are catching will change the behavior of your application.
Now reading the code of team members I can not be sure if they forgot
to throw or if this is the intended behaviour.
This is something the author of the code can explain to you. But here is a learning to take from this. Your code should be self explanatory. In specific cases where you are unable to express yourself with the code, add a meaningful comment.
You can check this link for better understanding.
I actually found another way that kind of includes what other have suggested here, but uses a built in feature: exception filters. I was free to modify the example given in here to illustrate this:
public void MethodThatFailsSometimes()
{
try {
PerformFailingOperation();
}
catch (Exception e) when (e.LogAndBeCaught())
{
}
}
and then one could have two extension methods on Exception, say LogAndBeCaught and LogAndEscape like so:
public static bool LogAndBeCaught(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return true;
}
public static bool LogAndEscape(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return false;
}

try/catch and returning values

I have a method that returns a List. Now I want to know how to place the try/catch blocks properly. If I place the return statement inside try I get error
Not all code paths return a value
If I place after catch(like I'm doing currently) it will return the products even after an Exception. So what should be the best way?
Here is the method:
public List<Product> GetProductDetails(int productKey)
{
List<Product> products = new List<Product>();
try
{
using (SqlConnection con = new SqlConnection(_connectionString))
{
SqlCommand cmd = new SqlCommand("usp_Get_ProductDescription", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#riProductID", productKey);
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Product product = new Product(reader["Name"].ToString(), reader["Code"].ToString());
products.Add(product);
}
}
}
}
catch { }
return products;
}
Remove the complete Try and Catch blocks. Apparently you are unable to handle the exceptions in the GetProductDetails method so just let them be thrown.
However the calling code can make the decision:
IList<Product> products = null;
try
{
products = GetProductDetails(3);
}
catch(Exception ex)
{
// Here you can make the decision whether you accept an empty list in case of retrieval errors.
// It is the concern of this method, not of the ProductDetails method.
// TODO: Use logging
products = new List<Product>();
}
I can imagine it feels like code duplication if you have to write this in every method using the GetProductDetails method. However consider, when you have X implementations, you want to react differently to not being able to get product details. You will have to come up with workarounds. You might even end up with weird bugs which are hard to troubleshoot.
That depends on what should happen in an exceptional case. If this might happen for some reason which isnĀ“t "bad enough" to let the app crash or if you are able to handle that exception appropriately then you might go with your current appraoch - however you should definitly leave at least a log-message within the catch-clause that contains the error which has been thrown:
catch (Exception e)
{
log.Info(e.Message);
}
This way you get all results within your list except those that caused any exceptions. You can simply continue work with all the results that you got and ignore those errorous (supposing you logged them in any way).
If it is a really unexpected behaviour (which is the intended one for exceptions, this is why they are called exceptions) you should delete all this try/catch from within your method and handle any exceptions outside the method as Maurice already mentioned.
At the moment, you don't return anything if an exception is thrown.
Use try, catch, finally. (May you want to see the MSDN page for more official information)
try
{
//try to execute this code
}
catch
{
//execute this if an exception is thrown
}
finally
{
//execute this code, after try/catch
}
So if you place your return statement into the finally section, you will return your list even if there's an exception thrown...

Check if exception is handled on higher level

Is there a way to check if exception is handled on a higher application level to skip logging and re-throw? Like this, for example:
try
{
// Execute some code
}
catch (Exception e)
{
if(!ExceptionIsHandled())
LogError(e);
throw e;
}
Nothing that I'm aware of. If you're committed to this design (see note at end), you could write a wrapper for an Exception that's some sort of HandledException and just make its InnerException be the one that was thrown. Then you could make your code look like:
try
{
// Execute some code
}
catch (HandledException e)
{
LogError(e.InnerException);
// Do something else
}
catch (Exception e)
{
throw ;
}
Here comes the stereotypical Stackoverflow "you're doin it wrong" part of the answer...
However, if you've truly "handled" the exception, it doesn't make a lot of sense to be re-throwing it. Maybe your method should just return a failure result, possibly including the Exception as a detail item for what went wrong.
This is old, but I do have some input here. There is a design pattern I've used before that does this very well, but does add a little bit of overhead to everything.
Basically, all methods would return a response object (e.g., Response<T>). Any exceptions that occur should be wrapped in the response object and returned instead of thrown.
public class Response<T>
{
public T Payload { get; set; }
public bool IsSuccessful { get; set; } = false;
public string Message { get; set; }
public Exception Error { get; set; }
}
public class MyService
{
public Response<IEnumerable<Customer>> GetCustomers()
{
var response = new Response<IEnumerable<Customer>>();
try
{
var customers = new List<Customer>()
{
new Customer() { CompanyName = "ABC Co." },
new Customer() { CompanyName = "ACME" }
};
response.Payload = customers;
response.IsSuccessful = true;
}
catch (Exception e)
{
response.IsSuccessful = false;
response.Error = e;
// A friendly message, safe to show to users.
response.Message = "An error occurred while attempting to retrieve customers.";
}
return response;
}
}
You can bubble up the exception without rethrowing it, and handle appropriately. You can then add exception catches for more custom user-friendly messages.
I also use a custom base Exception type for any errors that are safe to show the client. This way I can add a generic catch at the controller level to propagate those prepared error messages.
Well no, hasn't got there yet has it. Exceptions bubble up through handlers.
Usual way to go about this.
Is define your own exceptions, then only catch the ones you are going to handle where you are.
If you could be certain that code was wrapped within a specially-designed try-catch block which was written in a language that supports exception filters, it would be possible to determine before or during stack unwinding whether the exception was likely to be caught by that outer block or by an inner one. The usefulness of this is rather limited, however, especially given the extremely common anti-pattern of code catching and rethrowing exceptions that it knows it's not going to resolve, simply for the purpose of finding out that they occurred.
If your goal is simply to avoid redundant logging, I'd suggest that you should use a logging facility which can deal efficiently with redundancy. While some people might argue that it's better to have exceptions logged just once at the outer layers, there are advantages to having more logging opportunities. If an exception occurs within the inner layer and a middle layer swallows it, logging code within the outer layer will never find out about it. By contrast, if the inner layer starts out by capturing the exception and arranging for it to get logged, then even if the middle layer swallows the exception the fact that it occurred could still get recorded.

How to rethrow exceptions in a program with multiple layers?

I have an MVC EF5 setup, with classes:
Program - this is the controller
UserInterface - this is the view, responsible for displaying and prompting for data.
DataAccess - Model, this Creates, Reads, Updates, and Deletes data in my EF model classes
When the DataAccess class tries to do a CRUD operation on my database, if it catches an error, it needs to be handled, my UserInterface class needs to print messages to the user, reporting any errors if neccessary. So, when an error happens, it needs to go through the program class first, then to the UserInterface class, because data layer shouldn't directly communicate to the presentation layer.
It was suggested to me that I don't pass or return the exception to a calling function, but that I should "throw a new simpler exception to the layers above". All this talk about exceptions is confusing to me because My experience with exceptions is limited to this format:
try
{
// stuff
}
catch (exception ex)
{
console.writeline(ex.ToString());
}
I've done some of my own research to try and find the answer to this problem, and I've learned a few things but don't know how to put it all together:
I learned:
throw; rethrows an exception and preserves the stack trace
throw ex throws an existing exception, such as one caught in a catch block. and resets the stack trace.
There is a property called Exception.StackTrace. I understand that each time an exception is thrown, the frames in the call stack are recorded to the Exception.StackTrace property.
However, I don't know where to place my try/catch blocks to utilize rethrowing
Is it something like the following code? Or am I missing the point on how this works?
EDITED: (added a little more to make sense of this guesswork to others)
void MethodA()
{
try
{
MethodB();
}
catch (MyExceptionType ex)
{
// Do stuff appropriate for MyExceptionType
throw;
}
}
void MethodB()
{
try
{
MethodC();
}
catch (AnotherExceptionType ex)
{
// Do stuff appropriate for AnotherExceptionType
throw;
}
}
void MethodC()
{
try
{
// Do Stuff
}
catch (YetAnotherExceptionType ex)
{
// Do stuff appropriate for YetAnotherExceptionType
throw;
}
}
There is more than how you use different type of exception handling. Functionally you should define what layers has to do what with a exception.
Like data layer => dont throw anything other than DataException or SQLException. Log them and throw back a generic database exception back to UI.
Business layer => log and rethrow simple bussiness exception
UI layer => catch only business exception and alert it in a message inside business exception
Once all this is defined, you can use what you have learned and summarized in question to build this.
What (I think) was suggested you do by throw a new simpler exception is that you translate the exceptions from the lower layers into new, higher level exceptions for consuming in the outer layers. The lower level exceptions are not suitable for consumption at the upper levels of the program.
For example, in LINQ to Entities, the method Single() will throw an InvalidOperationException when the sequence has no elements. However, this exception type is very common, so catching it in the user interface levels is hard to do: how would you differentiate between different possibilities of this exception being thrown (for example, modifying a read-only collection)? The solution is to translate the exception into another (new, user-defined) type that the application can easily handle.
Here is a simple example of the idea:
public class MyUserService {
public User GetById(int id) {
try {
using(var ctx = new ModelContainer()) {
return ctx.Where(u => u.Id == id).Single();
}
}
catch(InvalidOperationException) {
// OOPs, there is no user with the given id!
throw new UserNotFoundException(id);
}
}
}
Then the Program layer can catch the UserNotFoundException and know instantly what happened, and thus find the best way to explain the error to the user.
The details will depend on the exact structure of your program, but something like this would work in an ASP.NET MVC app:
public class MyUserController : Controller {
private MyUserService Service = new MyUserService();
public ActionResult Details(int id) {
User user;
try {
user = Service.GetById(id);
}
catch(UserNotFoundException) {
// Oops, there is no such user. Return a 404 error
// Note that we do not care about the InvalidOperationException
// that was thrown inside GetById
return HttpNotFound("The user does not exist!");
}
// If we reach here we have a valid user
return View(user);
}
}

C# "using" statement and try/catch

Ive been doing some research today on when an how to use the "using" statement to dispose of my sql objects.
However I'm still confused about when and how to catch unforseen errors. I have a simple method here and would appreciate any input on wheter its correct or I'm doing something wrong?
private BindingList<My_Object> Search(int ID)
{
string strSelectStatement =
"SELECT 'coloumns' " +
"FROM 'table' " +
"WHERE ID = #ID;";
DataTable dt = new DataTable();
try
{
using (SqlConnection sqlConn = new SqlConnection(m_SQLConnectionString))
{
using (SqlCommand cmd = new SqlCommand(strSelectStatement, sqlConn))
{
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = ID;
using (SqlDataAdapter adpt = new SqlDataAdapter(cmd))
{
adpt.Fill(dt);
}
}
}
My_Object myObject;
BindingList<My_Object> myObjectList = new BindingList<My_Object>();
foreach (DataRow row in dt.Rows)
{
myObject = new My_Object();
//Fill/set myObject properties and add to myObject list
}
return myObjectList;
}
catch (Exception)
{
//throw the the exception with its stack trace up to the main call
throw;
}
}
So what my catch here would do is catch an error if anything went wrong when running adapter.Fill, or while building myObject/list for example.
Thanks
In C# . The using statement defines the scope of an item to be disposed. This can be called for any object which implements the IDisposable interface.
http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
So if you had to not use using blocks you would call the dispose method on the class to release/clean up resources created by the object.
When calling a class that implements the IDisposable interface, the try/finally pattern make sure that unmanaged resources are disposed of even if an exception interrupts your application.
If an exception is thrown in the case of a using statement the dispose will still be called. You can also stack using statements
using (SqlConnection sqlConn = new SqlConnection(m_SQLConnectionString))
using (SqlCommand cmd = new SqlCommand(strSelectStatement, sqlConn))
{
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = ID;
using (SqlDataAdapter adpt = new SqlDataAdapter(cmd))
{
adpt.Fill(dt);
}
}
with regards to exception handling. It is not wise to catch all exceptions try to catch the specific exceptions thrown by the class or method. You can view exception details on msdn so SQLConnection : http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.open.aspx
InvalidOperationException
Cannot open a connection without specifying a data source or server.
or
The connection is already open.
SqlException
A connection-level error occurred while opening the connection. If the Number property contains the value 18487 or 18488, this indicates that the specified password has expired or must be reset. See the ChangePassword method for more information.
So these are the exceptions you should cater for. Hope that helps!
Don't catch 'unforeseen' errors, since there's nothing you can do if truly unforeseen.
Unless of course you are wishing to handle these errors in some way, say, to log messages - but the system does that for you - then they are no longer 'unforeseen', since you're expecting them.
As for the code posted, there are problems. Firstly, the try / catch could be said to be trying too much, and given that you have usings in there, that is pointless (if exceptions aren't going to be handled.) It also catches a generic exception, which is highly discouraged; catches should be formulated to filter those that you can handle, and in appropriate order. To catch just to throw is also pointless.
Don't catch exceptions if you can do nothing about it. If you catch them is in order to clean up the unmanaged ressources or for logging purposes.
You might have a look on MSDN "Best Practices for Handling Exceptions" http://msdn.microsoft.com/en-us/library/seyhszts.aspx
You don't need the try..catch {throw}. This is the same as not having a try..catch block at all.
If you want to log the error of display a friendly message, then put the code in the catch { }.
The Dispose will still be called on the SqlConnection, even if the code crashes.
You can catch multiple exceptions at the end of your try statement. This means you can catch each different type of error that could occur i.e. InvalidOperationException / SqlException. MSDN Explains here:
http://msdn.microsoft.com/en-us/library/ms173162(v=vs.80).aspx
Since you have enclosed your whole code in try/Catch it will catch all errors raised within try/catch code block.
But don't follow this apprach only catch those errors specifically which you want to handle or log.
this is recommended because catching error is an overhead.

Categories

Resources