2011-01-11 17 views
5

Próbuję przechwycić wyjątek bazy danych, gdy serwer bazy danych jest wyłączony. Używamy Sybase IAnywhere.Dlaczego nie można uchwycić wewnętrznego wyjątku?

Używam zwykłego catch C# try, aby uzyskać nazwę wyjątku bazy danych.

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); 
} 

Druk na wyjątek to:

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) 

Więc myślę, że iAnywhere.Data.SQLAnywhere.SAException jest prawdziwy wyjątek powinien sobie radzić. Potem dodał zaczep do niego:

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); 
} 

Ale iAnywhere.Data.SQLAnywhere.SAException nie zaciął. Nadal łapię Exception. czemu?

+0

Czy można rozwinąć także "// kod tutaj", czy jest to kod wokół linii 158 pliku app.xaml.cs? – NotMe

+0

Ponadto, czy jesteś * pewien * to jest wdrożony kod? – NotMe

+0

"// kod tutaj" oznacza kod do połączenia z bazą danych w celu pobrania. I celowo zamykam serwer db. Dostaję więc wyjątek od bazy danych. – 5YrsLaterDBA

Odpowiedz

4

Ponieważ to, co zostało rzucone, nie jest wyjątkiem SAException. Spróbuj wydrukować wyjątek bezpośrednio, zamiast wywoływać GetBaseException().

1

Sprawdź, jaki jest faktyczny wyjątek. Twoje wywołanie GetBaseException() może maskować rzeczywisty wyjątek, który się pojawia.

6

Catch zajmuje się typem rzeczywistego wyjątku, który został zgłoszony, natomiast GetBaseException zwraca (pierwszy) InnerException, jeśli taki istnieje.

Wydrukuj rzeczywisty wyjątek, aby zobaczyć jego konkretny typ (lub sprawdź go w debugerze lub czymkolwiek innym), a następnie go złap.

+3

Nie pierwszy, najgłębszy –

+0

Tak - to jest bardziej semantycznie właściwy sposób, aby to ująć. +1 –

+0

Ah, teraz widzę, jak możesz najpierw oznaczać to samo (pierwszy wyrzucony). Cóż, teraz nie ma żadnej niejednoznaczności. –

3

To nie jest wyjątek SAException, to wewnętrzny wyjątek. Nie jest jasne z wykresu stosu, jaki jest typ zewnętrznego wyjątku. Łatwo dowiedzieć się z debugera lub jakiś kod diagnostyczny:

catch (Exception ex) { 
    Console.WriteLine(ex.GetType().FullName; 
    //... 
} 
1

może trzeba zrobić coś takiego:

try 
{ 
    //code here 
} 
catch (Exception ex) 
{ 
    if (ex.GetBaseException() is iAnywhere.Data.SQLAnywhere.SAException) 
    { 
     // log or handle known exception 
    } 
    else 
    { 
     // log unexpected exception 
    } 
} 

W innych odpowiedzi stwierdziły, można poprawić tego, jeśli wiesz, że rzeczywisty typ wyjątku, zmieniając Exception w powyższym kodzie na określony typ wyjątku.

Powiązane problemy