The best way to explain my question is with the following pseudo-code:
try
{
//Do work
}
catch (SqlException ex)
{
if (ex.Number == -2)
{
debugLogSQLTimeout(ex);
}
else
{
//How to go to 'Exception' handler?
}
}
catch (Exception ex)
{
debugLogGeneralException(ex);
}
Exception ex = null;
try
{
//Do work
}
catch (SqlException sqlEx)
{
ex = sqlEx;
if (ex.Number == -2)
{
//..
}
else
{
//..
}
}
catch (Exception generalEx)
{
ex = generalEx;
}
finally()
{
if (ex != null) debugLogGeneralException(ex);
}
The first catch clause that matches is the only one that can possibly run on the same try block.
The best way I can think of to do what you're attempting is to include casts and conditionals in the more general type:
try
{
//Do work
}
catch (Exception ex)
{
var sqlEx = ex as SqlException;
if (sqlEx != null && sqlEx.Number == -2)
{
debugLogSQLTimeout(ex);
}
else
{
debugLogGeneralException(ex);
}
}
If you find yourself writing this over and over again throughout your data layer, at least take the time to encapsulate it in a method.
I do not believe there is any way to do this as the catch blocks are in different scopes. There's no way to re-throw without exiting the try block and no way to 'call' the final catch block because it's only triggered during an exception.
I would suggest the same as roman m above and just make the same call. Otherwise you have to do something really bad. Like the below crazy code which you should never ever use but i included because it does something like what you want.
In general I think what you are doing is controlling normal flow via exceptions which isn't recommended. If you are trying to track for timeouts, you should probably just handle that another way.
Note that you could do something like the code below with the insanity of a goto statement, but i included it so no one can forget what a bad idea this is. =)
void Main()
{
Madness(new NotImplementedException("1")); //our 'special' case we handle
Madness(new NotImplementedException("2")); //our 'special' case we don't handle
Madness(new Exception("2")); //some other error
}
void Madness(Exception e){
Exception myGlobalError;
try
{
throw e;
}
catch (NotImplementedException ex)
{
if (ex.Message.Equals("1"))
{
Console.WriteLine("handle special error");
}
else
{
myGlobalError = ex;
Console.WriteLine("going to our crazy handler");
goto badidea;
}
}
catch (Exception ex)
{
myGlobalError = ex;
Console.WriteLine("going to our crazy handler");
goto badidea;
}
return;
badidea:
try{
throw myGlobalError;
}
catch (Exception ex)
{
Console.WriteLine("this is crazy!");
}
}
// Define other methods and classes here
Related
In my API, I have over 25 API controllers, in every controller, using the following code to catch exception, I think it is too many code here, any good suggestion for the structure, thanks.
try
{
*code here*
}
catch (UnauthorizedAccessException ex)
{
}
catch (BadRequestException ex)
{
}
catch (HttpRequestException ex)
{
}
catch (TimeoutRejectedException ex)
{
}
catch (FileNotFoundException ex)
{
}
catch (SqlException ex)
{
}
catch (ValidationException ex)
{
}
catch (Exception ex)
{
}
Any simple way to do that.
IF
you plan to handle each exception separately - your approach is the way to go. I suggest to use this "ugly" code simply because it is more readable. If all your exceptions have common handling (for example logging) - you can use only catch (Exception e) and call your logging methods. This will work for all types of exceptions.
OR
If you decide that some of your exceptions might have common handling - you can go with:
try
{
// do
}
catch (Exception e)
{
if (e is BadRequestException ||
e is HttpRequestException ||
e is TimeoutRejectedException )
{
// Log exception
}
}
OR
A good approach is to use a delegate for exception handling. Since you're going to log exceptions, the delegate will handle this.
Action<Exception> HandleError = (e) => {
// Log exception
};
catch (UnauthorizedAccessException e) { HandleError(e); }
catch (BadRequestException e) { HandleError(e); }
catch (HttpRequestException e) { HandleError(e); }
OR
You can combine the first and the second approach
if (e is BadRequestException ||
e is HttpRequestException ||
e is TimeoutRejectedException )
{
HandleError(e);
}
I'm trying to catch a duplicate key violation. I can see the System.OleDB.OleDBException in the Intellisense pop up, but the inner exception is null. How do I access the Error Code in the System.OleDB.OleDBException?
Greg
try
{
MyData.ConExec(sSQL);
}
catch (Exception ex)
{
OleDbException innerException = ex.InnerException as OleDbException;
if (innerException.ErrorCode == -2147217873)
{
// handle exception here..
}
else
{
throw;
}
}
don't declare an instance of the exception. It will surely return empty if you do.
try
{
MyData.ConExec(sSQL);
}
catch (OleDbException ex)
{
// handle excpetion here...
if (ex.ErrorCode == -2147217873)
{
}
}
catch (Exception e)
{
// if other exception will occur
}
I want to throw an exception at next catch, (I attached image)
Anybody know how to do this?
C# 6.0 to the rescue!
try
{
}
catch (Exception ex) when (tried < 5)
{
}
You can't, and trying to do so suggests that you've got too much logic in your catch blocks, or that you should refactor your method to only do one thing. If you can't redesign it, you'll have to nest your try blocks:
try
{
try
{
...
}
catch (Advantage.Data.Provider.AdsException)
{
if (...)
{
throw; // Throws to the *containing* catch block
}
}
}
catch (Exception e)
{
...
}
On the other hand, as of C# 6, there are exception filters so you can check a condition before actually catching the exception:
try
{
...
}
catch (Advantage.Data.Provider.AdsException) when (tries < 5)
{
tries++;
// etc
}
// This will catch any exception which isn't an AdsException *or* if
// if the condition in the filter isn't met.
catch (Exception e)
{
...
}
One possibility is nesting the try/catch clause:
try
{
try
{
/* ... */
}
catch(Advantage.Data.Provider.AdsException ex)
{
/* specific handling */
throw;
}
}
catch(Exception ex)
{
/* common handling */
}
there is also another way - using only your general catch statement and checking the exception type yourself:
try
{
/* ... */
}
catch(Exception ex)
{
if(ex is Advantage.Data.Provider.AdsException)
{
/* specific handling */
}
/* common handling */
}
This answer is inspired by Honza Brestan's answer:
}
catch (Exception e)
{
bool isAdsExc = e is Advantage.Data.Provider.AdsException;
if (isAdsExc)
{
tried++;
System.Threading.Thread.Sleep(1000);
}
if (tried > 5 || !isAdsExc)
{
txn.Rollback();
log.Error(" ...
...
}
}
finally
{
It's ugly to have two try blocks nested inside each other.
If you need to use properties of the AdsException, use an as cast instead of is.
I dont want to catch some exception. Can I do it somehow?
Can I say something like this:
catch (Exception e BUT not CustomExceptionA)
{
}
?
try
{
// Explosive code
}
catch (CustomExceptionA){ throw; }
catch (Exception ex)
{
//classic error handling
}
try
{
}
catch (Exception ex)
{
if (ex is CustomExceptionA)
{
throw;
}
else
{
// handle
}
}
Starting with C# 6, you can use an exception filter:
try
{
// Do work
}
catch (Exception e) when (!(e is CustomExceptionA))
{
// Catch anything but CustomExceptionA
}
You can filter it:
if (e is CustomExceptionA) throw;
And of course you can catch it and rethrow it:
try
{
}
catch (CustomExceptionA) { throw; }
catch (Exception ex) { ... }
First off, it's bad practice to catch Exception unless you log and re-throw it. But if you must, you need to catch your custom exception and re-throw it like so:
try
{
}
catch (CustomExceptionA custome)
{
throw custome;
}
catch (Exception e)
{
// Do something that hopefully re-throw's e
}
After being schooled by #Servy in the comments, I thought of a solution that'll let you do [what I think] you want to do. Let's create a method IgnoreExceptionsFor() that looks like this:
public void PreventExceptionsFor(Action actionToRun())
{
try
{
actionToRun();
}
catch
{}
}
This can then be called like this:
try
{
//lots of other stuff
PreventExceptionsFor(() => MethodThatCausesTheExceptionYouWantToIgnore());
//other stuff
}
catch(Exception e)
{
//do whatever
}
That way, every line except for the one with PreventExceptionsFor() will throw exceptions normally, while the one inside PreventExceptionsFor() will get quietly passed over.
I have a try and catch where I am catching different error types:
catch (XmlException XmlExp)
{
return false;
}
catch (XmlSchemaException XmlSchExp)
{
return false;
}
catch (Exception GenExp)
{
throw GenExp;
}
Notice that XMLException XMLExp is declared but never used. Is it possible to catch the XMLException without declaring a local variable?
Is this valid code:
catch (XmlException)
{
return false;
}
Yes, like this
catch (XmlException)
{
return false;
}
catch (XmlSchemaException)
{
return false;
}
catch (Exception GenExp)
{
// inspect or use GenExp
throw;
}
Do this
catch (XmlException)
{
return false;
}
catch (XmlSchemaException)
{
return false;
}
catch (Exception)
{
throw;
}
Just use
catch (XmlException)
{
throw;
}
When you throw a specific exception object like throw ex the stack trace gets overridden.
Yes. Just miss out the variable name:
catch (XmlException)
{
return false;
}
Yes you can:
catch (XmlException)
{
return false;
}
Of course, all other rules regarding exceptions apply - i.e. not using them for flow control, avoiding any situations where they might be thrown, etc.
catch (XmlException)
{
return false;
}
catch (XmlSchemaException)
{
return false;
}
catch (Exception GenExp)
{
throw GenExp;
}
Just omit the variable name.
For the last catch I'd advise using throw; instead of throw GenExp - as the latter loses the call stack. Although if you're really doing nothing more than a rethrow then just omit the whole catch block.
catch (Exception unknownException)
{
throw new Exception("Unknown error.", unknownException);
}
catch
{}
Is also valid code and catches all exceptions.
Important Notice!
It is a extremely BAD programming style - to use of similar constructions:
try
{
// smth
}
catch(IOException e)
{
throw e;
}
It means, that the exception stack will begin with this point (of stack), and you can lose any stack frames, which are lower than this point.
Correct:
try
{
//smth
}
catch(IOException e)
{
throw;
}
1- i think you was supposed to do this by yourself.
2- catch (XmlException) //valid
{
return false;
}
catch (XmlSchemaException) //valid
{
return false;
}
catch (Exception GenExp)
{
throw GenExp;
}
//valid but doesn't make sense because the Exception will happen and there is no try catch block to handel it