tags:

views:

194

answers:

5

How can I catch an inner exception in .NET? I need to check 2 databases for a record. The database code throws an exception if a record is not found, so then I want to check the second database:

Try
     # Code to look in database 1
Catch ex as DataServiceQueryException
     Try
          # Code to look in database 2
     Catch ex2 as DataServiceQueryException
          throw New DataServiceQueryException(ex.Message, ex2) # Fails here
     End Try
Catch ex as Exception # Why doesn't ex2 land here?
   # Tell user that data was not found in either database
End Try

The above pseudo-code fails at 'Fails here and ex2 never is handled by my code.

How should I properly handle the inner exception?

+1  A: 

An inner exception by definition has already been handled and repackaged as another exception. You have to handle the outer exception, and then if necessary/appropriate process the inner one in the catch block of the outer exception.

John Weldon
Hmm, that's what I attempted to do with `Catch ex as Exception`. I thought the inner exception would just be caught by the outer `Catch`.
Slack
+10  A: 

The reason your current code doesn't work is that once you enter the catch section, you've already left the try block. Instead, do it like this:

Try
   ''# Check Database 1
Catch
    Try
        ''# Check Database 2
    Catch
         ''# Tell the user that data was not found in either database
    End Try
End Try

Or like this:

Dim FoundFlag as Boolean = False
Try
    ''# Check Database 1
    FoundFlag = True
    ''# Best if you can just return "False" and avoid the exception altogether
Catch
End Try

If Not FoundFlag Then
    Try
        ''# Check Database 2
        FoundFlag = True
    Catch
    End Try
End If

If Not FoundFlag Then
     ''# Tell the user that data was not found in any database
End If
Joel Coehoorn
Thanks. The first example works perfectly. Unfortunately, I can't avoid the exception. The "database" is an Azure REST service which returns 404 if a record is not found. This causes the REST wrapper to throw an exception.
Slack
P.S. I guess I didn't need to throw the inner exception at all.
Slack
A: 

I would say, based on the pseudo-code, that it's because the exception you're throwing on line 7 is inside the "try" block surrounding line 3 so the "catch" on line 9 simply doesn't apply.

Edit: what Joel said.

Andrew Medico
A: 

First, if you are using try/catch, you should probably have a finally to clean up the resources. That being said, having nested try/catch blocks us usually a code smell. Do you have to implement it that way? Why does the server just fail? Why couldn't the Data Layer just pass a status message? Exceptions should be, well, "exceptional".

If you have to use exceptions, "Joel Coehoorn"'s way seems good.

Charles Graham
Slack
A: 

I am agreeing with Joel and I wish to further recommend that you sit down and decide which of the following cases you really wish to happen and then code accordingly.

Case A. If record11 exists in db1 then check if record22 exists in db2

try{
  getRecord11;

  try
  {
    getRecord22;
  }
  catch ex22
  {
    saySorry2;
  }
}
catch ex11
{
  saySorry1;
}

case B. If record11 does not exist in db1 then check if record22 exists in db2

try{
  getRecord11;
}
catch ex11
{
  saySorry1;

  try
  {
    getRecord22;
  }
  catch ex22
  {
    saySorry2;
  }
}

case C. Get record11 from db1. Regardless of db1 results, get record22 from db2.

try{
  getRecord11;
}
catch ex11
{
  saySorry1;
}

try
{
  getRecord22;
}
catch ex22
{
  saySorry2;
}
Blessed Geek
Thanks for your post. I'm pretty much case B, except that my scenario is "Get record11 from db1. If fails, get record11 from db2. If fails, saySorry". Thanks for your examples.
Slack