Working with Exception Chains


Suppose you write a class called Checking, and Checking inherits from a class called Account. Then suppose that the Checking class has a method called OrderChecks . Some code in your program creates an instance of the Checking class and calls the OrderChecks method, and gets an exception. Let's say the exception object is of type OrderChecksException .

But perhaps the exception originated as the result of another exception in the Account class. Let's say that there is a $5 fee for ordering checks, and the particular account involved in the request has a balance of zero dollars (the story of my life). So the exception might have originated in Account as AccountOverdrawnException , but the OrderChecks method catches the exception and decides to throw a different exception that is specific to ordering checks ( OrderChecksException ). Instead of discarding the AccountOverdrawnException object, a developer may choose to chain the exceptions. The developer calling the OrderChecks method would then be able to catch the OrderChecksException but would also be able to obtain information about the AccountOverdrawnException and any other exceptions involved in the process of ordering checks.

To navigate through an exception chain:

  1. In a catch block for a specific exception, test if the InnerException property is not equal to null.

  2. If the InnerException property is not null, save the value of InnerException in a variable.

  3. The new variable now contains another exception object that also has an InnerException property.

  4. Repeat steps 1 through 3 until InnerException is null.

graphics/tick.gif Tips

  • Steps 1-4 can easily be combined into a simple while loop ( Figure 11.15 ).

    Figure 11.15 This loop ensures that you record the message for every inner exception.
     //using System.Data.OleDb; void OpenDatabase() {    string cstr =    "Provider=Microsoft.Jet.OLEDB.4.0;"    + @"Data Source=c:\csvqs.mdb;";    try    {       IDbConnection conn = new       OleDbConnection(cstr);       conn.Open();    }    catch(OleDbException e)    {       string Msg = "Database Error:<br>";       Msg += e.Message;       Response.Write(Msg);    }    catch(System.Exception e)    {       string Msg = "General error:<br>";       Msg += e.Message;  while (e.InnerException != null)   {   e = e.InnerException;   Msg += e.Message + "<br>";   }  Response.Write(Msg);    } } 
  • Whenever you catch an exception, it's a good idea to check if the InnerException property is not null to ensure that you aren't neglecting other information about the exception.

  • Every exception object has an InnerException property, but some classes may choose to report chains of errors with a custom property. For example, ADO .NET classes often use an Errors property. The Errors property is an array of errors rather than a chain. (In a chain one node points to another node, which points to another, and so on.) In an array, you can jump to any one error at a given time. Figure 11.16 shows how to handle ADO.NET exceptions.

    Figure 11.16 Even though .NET has a mechanism for reporting nested exceptions with the InnerException property, ADO.NET reports related errors through the Errors collection. This lets you jump directly to a particular error rather than navigate through a chain to find it.
     //using System.Data.OleDb; void OpenDatabase() {    string cstr =    "Provider=Microsoft.Jet.OLEDB.4.0;"    + @"Data Source=c:\csvqs.mdb;";    try    {       IDbConnection conn = new       OleDbConnection(cstr);       conn.Open();    }    catch(OleDbException e)    {  string Msg = "Database Error:<br>";   foreach (OleDbError err in   e.Errors)   {   Msg += e.Message + "<br>";   }   Response.Write(Msg);  }    catch(System.Exception e)    {       string Msg = "General error:<br>";       Msg += e.Message;       Response.Write(Msg);    } } 
  • You can use the function GetBaseException to navigate directly to the root exception: the first exception that was generated ( Figure 11.17 ).

    Figure 11.17 You'll need to use this technique later when we talk about unhandled exceptions. What happens with ASP.NET unhandled exceptions is that the error reported is just a general "there was an error" object. To get the specific exception that caused the program to halt you need to use the GetBaseException method.
     //using System.Data.OleDb; void OpenDatabase() {    string cstr =    "Provider=Microsoft.Jet.OLEDB.4.0;"    + @"Data Source=c:\csvqs.mdb;";    try    {       IDbConnection conn = new       OleDbConnection(cstr);       conn.Open();    }    catch(OleDbException e)    {  string Msg = "Database Error:<br>";   Msg += e.GetBaseException()   .Message;   Response.Write(Msg);  }    catch(System.Exception e)    {       string Msg = "General error:<br>";       Msg += e.Message;       Response.Write(Msg);    } } 



C#
C# & VB.NET Conversion Pocket Reference
ISBN: 0596003196
EAN: 2147483647
Year: 2003
Pages: 198
Authors: Jose Mojica

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net