Catch DB error details - c#

I want a better way to catch database error details.
I'm currently using :
try
{
dbconn.table.AddObject(newRow);
dbconn.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine("DB fail ID:" + Row.id);
}
many times I found the Exception ex can no give me details on how the exception happen.
I think these exception most likely to be the DB connection kind.
So is there a better way to catch this ?

You should also output the exception. Most of the time, it holds useful and detailed information (e.g. names of violated constraints). Try this:
try
{
dbconn.table.AddObject(newRow);
dbconn.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine("DB fail ID:" + Row.id);
Console.WriteLine(ex.ToString());
}
For full details, use the ToString() method, it will give you the stack trace as well, not only the error message.

Use Console.WriteLine(ex.GetType().FullName) (or put a breakpoint and run under a debugger) to see the actual exception type being thrown. Then visit MSDN to see its description and base classes. You need to decide which of the base classes provides you with the information needed by exposing such properties. Then use that class in your catch() expression.
For Entity Framework, you might end up with using EntityException and then checking the InnerException property for the SQL exception object that it wraps.
try
{
dbconn.table.AddObject(newRow);
dbconn.SaveChanges();
}
catch (EntityException ex)
{
Console.WriteLine("DB fail ID:" + Row.id + "; Error: " + ex.Message);
var sqlExc = ex.InnerException as SqlException;
if (sqlExc != null)
Console.WriteLine("SQL error code: " + sqlExc.Number);
}

Instead of Exception use SqlException.
SqlException give you more detail. it has a Number property that indicate type of error and you can use that Number in a switch case to give some related information to user.

In short, yes there is a better way to handle it. The 'how' of it is up to you.
Exception handling in C# goes from the most specific exception type to the least specific. Also, you aren't limited to using just one catch block. You can have many of them.
As an example:
try
{
// Perform some actions here.
}
catch (Exception exc) // This is the most generic exception type.
{
// Handle your exception here.
}
The above code is what you already have. To show an example of what you may want:
try
{
// Perform some actions here.
}
catch (SqlException sqlExc) // This is a more specific exception type.
{
// Handle your exception here.
}
catch (Exception exc) // This is the most generic exception type.
{
// Handle your exception here.
}
In Visual Studio, it is possible to see a list of (most) exceptions by pressing CTRL+ALT+E.

Related

How to differentiate between InvalidOperationException exception types?

How to detect the InvalidOperationException type
Here is the inner exception message:
System.InvalidOperationException: ExecuteNonQuery requires an open and available Connection. The connection's current state is closed.
I need to detect exactly this type of exceptions to handle it.
Can I know its HResult number or the exception code? or another way?
This code may help
try
{
//your code here...
}
catch (Exception exception) when (exception.InnerException is InvalidOperationException)
{
var exceptionMessage = "ExecuteNonQuery requires an open and available Connection";
if (exception.Message.Contains(exceptionMessage) || exception.InnerException.Message.Contains(exceptionMessage))
{
//handle it...
}
}
You can use a try/catch exception handling hierarchy, so that InvalidOperationException will be caught first and handled separately from other exception types such as the generic exception type.
try
{
// Normal workflow up here
}
catch (System.InvalidOperationException ioex)
{
// Handle InvalidOperationException
Console.WriteLine(ioex.StackTrace);
}
catch (System.Exception ex)
{
// Handle generic exception
Console.WriteLine(ex.StackTrace);
}
However, your question suggests that this will not work for you, because you mention an inner exception. In that case you probably need to do some type checking on the inner exception like this:
try
{
// Normal workflow up here
}
catch (System.Exception ex)
{
if (ex.InnerException is InvalidOperationException)
{
// Handle InvalidOperationException
}
else
{
// Handle generic exception
}
Console.WriteLine(ex.StackTrace);
}
Could you give us more context? It would make it easier for us to answer your question.
However, if I understand you correctly, you try to process 'something' with the inner exception. As of C# 6 there are exception filters available. For more information about exception filters see Exception filters.
The documentation also provides an example.
In your specific case, you could use the exception filter as follows:
try
{
// Do something that could cause a InvalidOperationException
}
catch (InvalidOperationException ex) when (ex.InnerException is SomeTypeOfException)
{
// Handle this type of exception
}
catch (InvalidOperationException ex) when (ex.InnerException is AnotherSomeTypeOfException)
{
// Handle this kind of exception
}

Using exception filtering in c# 6.0 (with typeof()) VS. catching custom exception

I have a method for manage exception handling as below. The Question is that, in case that the typeof exception is our point, which approach is recommended? Using
catch (System.Exception ex) when(ex.GetType() ==typeof(ExcOneException)){...}
or
catch (ExcOneException ex) {...}
public T MyMethod<T>(Func<T> codeToExecute)
{
try
{
return codeToExecute.Invoke();
}
catch (System.Exception ex) when(ex.GetType() ==typeof(ExcOneException) )
{
throw new ExcOneException(ex.Message,ex);
}
catch (System.Exception ex)
{
throw new ExcTwoException(ex.Message, ex);
}
}
UPDATE: My solution has 3 projects, UI, Services and DataAccess. Each part has its own custom Exception-Handler class. Imagine that, the code in question is in service project. All codes should call this method for execution. If there is any run-time error with type of ExcOneException, it means the error is in service section, else, there should be an error in data access part; so, ExcTwoException should be thrown. This approach helps me in bubbling error up to UI level with details. What I didn't know, was that, in the case that we can use C# 6 properties, when I have filtering just on exception type, which approach is better, using catch-when or mentioning exception type as argument of catch?
Simplification & Readability:
You can filter with is, instead of typeof:
catch (Exception ex) when (ex is ExcOneException) { ... }
Chain multiple Exception types:
catch (Exception ex) when (ex is ExcOneException || ex is ExcTwoException) { ... }
Why would you ever consider that? You mention performance. Do you have any measurements that make you suspicious.
Exception filters are there for filtering exceptions that you can't catch by type, which is not your case.
In your code you are, also, not re-throwing the caught exception. You are throwing an new exception with the caught exception as an inner exception which is what you do when you want to wrap the caught exception with a more meaningful one.
If you intention is to re-throw, the correct code is:
catch (System.Exception ex)
{
throw;
}

Is it ok to handle specific exception like this

I have seen such code in many places, is there any benefit of this..Or this is a wrong practice..
try
{
......
}
catch (NullReferenceException ex)
{
Data.LogError(ex, "Exception occourred while ...");
}
catch (IndexOutOfRangeException ex)
{
Data.LogError(ex, "Exception occourred while ...");
}
catch (Exception ex)
{
Data.LogError(ex, "Exception occourred while ...");
}
In context of specific exception handling.
There is benefit if you are going to handle the exceptions differently in the catch block (i.e. perform different actions as a result of the exception being thrown).
Otherwise you could remove the more specific exception handlers and just use the most generic:
catch(Exception ex)
Note: If the exception is being used purely for logging then sometimes it can be useful to re-throw the exception to bubble it up to the rest of the application:
try{
}
catch(Exception ex){
// Log exception here
throw;
}
This is even better than a generic catch, because you can choose what to do with a certain type of exception. Say, you want to show a message if a file doesn't exist, and offer to retry, but kill the application otherwise.
You can also handle exceptions differently, because they offer different properties (thanks to Rots for pointing that out):
try
{
}
catch(FileNotFoundException ex)
{
Console.WriteLine(ex.FileName + " not found");
//Retry
}
catch(Exception ex) // Exception does not contain ex.FileName
{
//Save stuff
//Exit
}
Only the first matching block will be executed.
The given approach is best in case if you wanted to handle/log any specific exception in it's own way. Also, ideal in scenario, where you can inform user with more apt details than giving generic messages. Now, if you don't want to handle different exceptions then you can goahead with one catch block, which catch all exception.

Try Catch handled at top of process

if I do this:
try
{
//code
}
catch (Exception)
{
throw;
}
Does the Exception go up with all its information?
The idea is to handle errors at the top of the app. There I'd execute some SQL sp to fill the admin's table so he's aware of exceptions.
I want to store Exception.Message and the source (method, function, whatever..) of the exception. But I don't know how to refer to "where" the exception happened. Is it Exception.Source? Exception.TargetSite?
Thanks.
The type of Exception will tell you what kind of exception it is (IndexOutOfRangeException, SqlException, etc) which you would react too accordingly:
try
{
//code
}
catch (SqlException ex)
{
// Handle code
}
catch (IndexOutOfRangeException ex)
{
// Handle code
}
catch (Exception ex)
{
// Handle code
}
As to where it is happening... you should be enclosing exception-prone areas with a try catch and not large code chunks. This way you will know where the exception derives from.
The Short answer is yes: just calling throw passes everthing regarding the exception up.
throw ex resets the stack trace (so your errors would appear to originate from HandleException)
throw doesn't - the original offender would be preserved.
(quoted from Mark Gravell)

C#: multiple catch clauses

Consider the following:
try {
FileStream fileStream = new FileStream("C:\files\file1.txt", FileMode.Append); }
catch (DirectoryNotFoundException e)
{ MessageBox.Show("Directory not found. " + e.Message); }
catch (IOException e)
{ MessageBox.Show("Other IO Error. " + e.Message); }
catch (Exception e)
{ MessageBox.Show("Other Error. " + e.Message); }
Will a DirectoryNotFoundException exception get handled by all three catch clauses or just the first one?
Just the first one. The exception doesn't propagate to all matching catch clauses.
From the C# 4 spec, section 8.9.5:
The first catch clauses that specifies the exception type or a base type of the exception type is considered a match. [...] If a matching catch clause is located, the exception propagation is completed by transferring control to the block of that catch clause.
Here the "completed" part indicates that after control has been transferred, that's the end of the special handling, effectively.
Only the first one. Catch-blocks doesn't fall through.
Only the first matching catch catches the exception, should you for any reason need to cacth it again you will have to throw it again so the "external" catch caluses will be able to catch it.
only the 1st one , the 1st matching catch clause will handle the exception
This is the correct way to handle exceptions - start with the most specific exception type and work back. Bare in mind however, if you can't do anything to resolve or handle an exception, don't catch it. For example, I'm assuming your code is in some file-access method, I would remove the last catch (Exception) block, as there's nothing you can do about it here (what if it's a stack overflow, out of memory or some other serious system exception...)

Categories

Resources