Почему нельзя поймать внутреннее исключение? - PullRequest
5 голосов
/ 11 января 2011

Я пытаюсь поймать исключение базы данных, когда сервер базы данных не работает. Мы используем Sybase IAnywhere.

Я использую обычный C # try catch, чтобы получить имя исключения из базы данных.

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

Распечатка исключения:

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)

Так что я думаю, iAnywhere.Data.SQLAnywhere.SAException - это настоящее исключение, с которым я должен справиться. Тогда я добавил улов для этого:

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

Но iAnywhere.Data.SQLAnywhere.SAException НЕ пойман. Я все еще поймаю Exception. почему?

Ответы [ 5 ]

6 голосов
/ 11 января 2011

Catch имеет дело с типом действительного исключения, которое было выдано, тогда как GetBaseException возвращает (первое) InnerException, если оно существует.

Распечатайте фактическое исключение, чтобы увидеть его конкретный тип (или проверить его в отладчике, или что-то еще), а затем поймайте это.

4 голосов
/ 11 января 2011

Потому что то, что выброшено, не является SAException.Попробуйте распечатать исключение напрямую вместо вызова GetBaseException ().

3 голосов
/ 11 января 2011

Это не SAException, это внутреннее исключение. Из трассировки стека неясно, что является внешним типом исключения. Легко узнать с помощью отладчика или диагностического кода:

catch (Exception ex) {
    Console.WriteLine(ex.GetType().FullName;
    //...
}
1 голос
/ 11 января 2011

Вам может потребоваться сделать что-то вроде этого:

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

Как указано в других ответах, вы можете улучшить это, если знаете фактический тип исключения, изменив Exception в приведенном выше коде на конкретный тип исключения.

1 голос
/ 11 января 2011

Проверьте, что является действительным исключением, через которое вы проходите.Ваш GetBaseException() вызов может маскировать действующее исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...