Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why cannot catch the inner exception?

I try to catch the database exception when database server is down. We use Sybase IAnywhere.

I use regular C# try catch to get the name of the database exception.

try
{
//code here
}
catch (Exception ex)
{
Logging.Log.logItem(LogType.Exception, "Exception in isDBRunning", "App_Startup::isDBRunning() ", "GetBaseException=" + ex.GetBaseException().ToString() + "\nMessage=" + ex.Message + "\nStackTrace: " + ex.StackTrace + "\nInnerException: " + ex.InnerException);
}

The exception print out is this:

GetBaseException=iAnywhere.Data.SQLAnywhere.SAException: Database server not found
   at iAnywhere.Data.SQLAnywhere.SAConnection.Open()
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
Message=The underlying provider failed on Open.
StackTrace:    at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   at System.Data.EntityClient.EntityConnection.Open()
   at System.Data.Objects.ObjectContext.EnsureConnection()
   at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
   at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__2[TResult](IEnumerable`1 sequence)
   at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
   at System.Linq.Queryable.Count[TSource](IQueryable`1 source)
   at Analogic.SystemSoftware.App.isDBRunning() in C:\workspace\SystemSoftware\SystemSoftware\src\startup\App.xaml.cs:line 158
InnerException: iAnywhere.Data.SQLAnywhere.SAException: Database server not found
   at iAnywhere.Data.SQLAnywhere.SAConnection.Open()
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)

So I think the iAnywhere.Data.SQLAnywhere.SAException is the real exception I should handle. Then I added a catch for it:

try
{
 //code here
}
catch (iAnywhere.Data.SQLAnywhere.SAException ex)
{
Logging.Log.logItem(LogType.Exception, "Exception in isDBRunning 1", "App_Startup::isDBRunning() ", "GetBaseException=" + ex.GetBaseException().ToString() + "\nMessage=" + ex.Message + "\nStackTrace: " + ex.StackTrace + "\nInnerException: " + ex.InnerException);
}

catch (Exception ex)
{
 Logging.Log.logItem(LogType.Exception, "Exception in isDBRunning", "App_Startup::isDBRunning() ", "GetBaseException=" + ex.GetBaseException().ToString() + "\nMessage=" + ex.Message + "\nStackTrace: " + ex.StackTrace + "\nInnerException: " + ex.InnerException);
}

But the iAnywhere.Data.SQLAnywhere.SAException is NOT caught. I still get the Exception caught. why?

like image 821
5YrsLaterDBA Avatar asked Jan 11 '11 15:01

5YrsLaterDBA


3 Answers

Catch deals with the type of the actual exception that has been thrown, whereas GetBaseException returns the (first) InnerException if any exist.

Print out the actual exception to see its specific type (or inspect it in a debugger, or whatever) and then catch that.

like image 147
Andrew Anderson Avatar answered Oct 15 '22 18:10

Andrew Anderson


Because what's thrown is not an SAException. Try printing out the exception directly instead of calling GetBaseException().

like image 43
Etienne de Martel Avatar answered Oct 15 '22 19:10

Etienne de Martel


It isn't SAException, that's the inner exception. It isn't clear from the stack trace what the outer exception type is. Easy to find out with the debugger or some diagnostic code:

catch (Exception ex) {
    Console.WriteLine(ex.GetType().FullName;
    //...
}
like image 30
Hans Passant Avatar answered Oct 15 '22 20:10

Hans Passant