2011-01-11 14 views
5

Intento atrapar la excepción de la base de datos cuando el servidor de la base de datos está inactivo. Usamos Sybase IAnywhere.¿Por qué no se puede capturar la excepción interna?

Utilizo C# try try catch para obtener el nombre de la excepción de la base de datos.

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

La excepción impresión es la siguiente:

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) 

Así que creo que el iAnywhere.Data.SQLAnywhere.SAException es la verdadera excepción que debería manejar. Luego añade una captura para ello:

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

Pero el iAnywhere.Data.SQLAnywhere.SAException no esté enganchado. Sigo atrapado en el Exception. ¿por qué?

+0

¿Puede ampliar "// code here" también, este es el código alrededor de la línea 158 de su archivo app.xaml.cs? – NotMe

+0

Además, ¿está * seguro * este es el código implementado? – NotMe

+0

"// code here" significa código para conectarse a la base de datos para recuperar. Y apago el servidor db a propósito. Entonces obtendré una excepción de la base de datos. – 5YrsLaterDBA

Respuesta

4

Porque lo que se arroja no es una SAExcepción. Intente imprimir la excepción directamente en lugar de llamar a GetBaseException().

1

Compruebe para ver cuál es la excepción real que ha recibido. Su llamada GetBaseException() podría enmascarar la excepción real que está ocurriendo.

6

Catch trata del tipo de la excepción real que se ha lanzado, mientras que GetBaseException devuelve el (primer) InnerException, si existe alguno.

Imprima la excepción real para ver su tipo específico (o inspecciónelo en un depurador, o lo que sea) y luego atrape eso.

+3

No es el primero, el más interno –

+0

Sí, esa es una forma más semánticamente correcta de decirlo. +1 –

+0

Ah, ahora veo cómo en primer lugar puede significar lo mismo (el primero arrojado). Bueno, no hay ambigüedad ahora en cualquier caso. –

3

No es SAException, esa es la excepción interna. No está claro desde el seguimiento de pila cuál es el tipo de excepción externa. Es fácil de encontrar con el depurador o algún código de diagnóstico:

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

Es posible que tenga que hacer algo como esto:

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

Como las otras respuestas han indicado, se puede mejorar esto si conoce la tipo real de la Excepción, cambiando Exception en el código anterior al tipo específico de la excepción.

Cuestiones relacionadas