2011-01-11 46 views
5

Tôi cố gắng nắm bắt ngoại lệ cơ sở dữ liệu khi máy chủ cơ sở dữ liệu bị hỏng. Chúng tôi sử dụng Sybase IAnywhere.Tại sao không thể bắt ngoại lệ bên trong?

Tôi thường xuyên sử dụng C# try catch để lấy tên của ngoại lệ cơ sở dữ liệu.

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

Ngoại lệ in ra là thế này:

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) 

Vì vậy, tôi nghĩ rằng iAnywhere.Data.SQLAnywhere.SAException là ngoại lệ thật tôi nên xử lý. Sau đó, tôi đã thêm một nội dung bắt buộc cho nó:

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

Nhưng không bị bắt gặp iAnywhere.Data.SQLAnywhere.SAException. Tôi vẫn bị bắt số Exception. tại sao?

+0

Bạn cũng có thể mở rộng trên "// mã ở đây" không, đây có phải là mã quanh dòng 158 của tệp app.xaml.cs của bạn không? – NotMe

+0

Ngoài ra, bạn có * chắc chắn * đây là mã được triển khai không? – NotMe

+0

"// mã ở đây" có nghĩa là mã để kết nối với cơ sở dữ liệu để thực hiện truy xuất. Và tôi tắt máy chủ db. Vì vậy, tôi sẽ nhận được ngoại lệ từ cơ sở dữ liệu. – 5YrsLaterDBA

Trả lời

4

Vì nội dung được ném không phải là SAException. Hãy thử in ra ngoại lệ trực tiếp thay vì gọi GetBaseException().

1

Kiểm tra xem ngoại lệ thực sự là bạn đang trải qua. Cuộc gọi GetBaseException() của bạn có thể đang che giấu ngoại lệ thực sự đang xảy ra.

6

Catch xử lý loại ngoại lệ thực tế đã được ném, trong khi GetBaseException trả lại (đầu tiên) InnerException nếu có.

In ngoại lệ thực tế để xem loại cụ thể của nó (hoặc kiểm tra nó trong trình gỡ rối hoặc bất kỳ thứ gì) và sau đó nắm bắt điều đó.

+3

Không phải là người đầu tiên, trong số –

+0

Vâng - đó là một cách ngữ nghĩa thích hợp hơn để đặt nó. +1 –

+0

Ah, bây giờ tôi thấy làm thế nào bạn lần đầu tiên có thể có nghĩa là cùng một điều (đầu tiên ném). Vâng, không có sự mơ hồ bây giờ trong mọi trường hợp. –

3

Nó không phải là SAException, đó là ngoại lệ bên trong. Nó không phải là rõ ràng từ ngăn xếp dấu vết những gì loại ngoại lệ bên ngoài là. Dễ dàng để tìm hiểu với trình gỡ lỗi hoặc một số mã chẩn đoán:

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

Bạn có thể cần phải làm một cái gì đó như thế này:

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

Như câu trả lời khác đã nêu, bạn có thể cải thiện điều này nếu bạn biết loại ngoại lệ thực tế, bằng cách thay đổi Exception trong mã ở trên thành loại ngoại lệ cụ thể.

Các vấn đề liên quan