1

In my method that writes to a database, I handle errors as shown in the code below. In catch (DbUpdateException ex) I want to re-throw the exception and catch it in the last catch (Exception ex).

Is that possible and how to do that? Code below doesn't do that.

        using (Entities context = new Entities())
        {
            try
            {
                context.Office.Add(office);
                retVal = context.SaveChanges();
            }
            catch (DbUpdateException ex)
            {
                SqlException innerException = ex.GetBaseException() as SqlException;
                if (innerException != null && innerException.Number == (int)SQLErrorCode.DUPLICATE_UNIQUE_CONSTRAINT)
                {
                    throw
                        new Exception("Error ocurred");
                }
                //This is momenty where exception is thrown.
                else
                {
                    throw ex;
                }
            }
            catch (Exception ex)
            {
                throw
                    new Exception("Error");
            }
        }
Rafael
  • 2,602
  • 4
  • 31
  • 49
SilverDeveloper
  • 187
  • 1
  • 12
  • 2
    You are losing all sorts of useful information here. The stacktrace keeps getting reset. – Henk Holterman Oct 16 '12 at 11:18
  • 2
    [Please don't use exceptions for flow control](http://stackoverflow.com/questions/729379/why-not-use-exceptions-as-regular-flow-of-control) – Paolo Moretti Oct 16 '12 at 11:20
  • 2
    Why would you want that? Your last catch will hide all the exception details, making it harder to debug and maintain. If you are not going to handle the exception, just let it bubble. – Oscar Oct 16 '12 at 11:17

6 Answers6

8

The following would be better:

context.Office.Add(office);
retVal = context.SaveChanges();

Let the except bubble up. No need to catch stuff if all you are going to do is re-throw.

Note: throw ex; will reset the stack trace - you want to do throw; normally.

Oded
  • 463,167
  • 92
  • 837
  • 979
3

If you want to catch exceptions from other catches then they cannot be on the same level.

Your current code has this structure:

try
{
}
catch (...)
{
}
catch (...)
{
}

You need to change it to:

try
{

    try
    {
    }
    catch (...)
    { 
       // throw X
    }                
}
catch (...)
{
   // catch X here
}

But you should think very carefully if you really want/need this. It does not look like a productive error handling pattern.

And see this answer for the 4 different ways to (re)throw an exception and their consequences.

Community
  • 1
  • 1
Henk Holterman
  • 236,989
  • 28
  • 287
  • 464
1

A try-catch processes only one catch block and they are evaluated in order. Therefore, if you really need this functionality you'll need to put a try-catch inside of a try-catch, like this:

using (Entities context = new Entities()) 
{ 
    try
    {
        try 
        { 
            context.Office.Add(office); 
            retVal = context.SaveChanges(); 
        } 
        catch (DbUpdateException ex) 
        { 
            SqlException innerException = ex.GetBaseException() as SqlException; 
            if (innerException != null && innerException.Number == (int)SQLErrorCode.DUPLICATE_UNIQUE_CONSTRAINT) 
            { 
                throw 
                    new Exception("Error ocurred"); 
            } 
            //This is momenty where exception is thrown. 
            else 
            { 
                throw ex; 
            } 
        } 
    }
    catch (Exception ex) 
    { 
        throw 
            new Exception("Error"); 
    } 

} 
Mike Perrenoud
  • 63,395
  • 23
  • 143
  • 222
1

have you tried try nesting your try...catch blocks?

using (Entities context = new Entities())
    {
        try
        {
            try
            {
                context.Office.Add(office);
                retVal = context.SaveChanges();
            }
            catch (DbUpdateException ex)
            {
                SqlException innerException = ex.GetBaseException() as SqlException;
                if (innerException != null && innerException.Number == (int)SQLErrorCode.DUPLICATE_UNIQUE_CONSTRAINT)
                {
                    throw new Exception("Error ocurred");
                }
                //This is momenty where exception is thrown.
                else
                {
                    throw ex;
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Error");
        }
    }
paul
  • 20,643
  • 1
  • 48
  • 53
0

Try this:

void YourMethod()
{
using (Entities context = new Entities())
        {
            try
            {
                context.Office.Add(office);
                retVal = context.SaveChanges();
            }
            catch (DbUpdateException ex)
            {
                SqlException innerException = ex.GetBaseException() as SqlException;
                if (innerException != null && innerException.Number == (int)SQLErrorCode.DUPLICATE_UNIQUE_CONSTRAINT)
                {
                    throw
                        new Exception("Error ocurred");
                }
                //This is momenty where exception is thrown.
                else
                {
                    throw ex;
                }
            }
        }
}

Then when you call your method enclose it with try catch block

try
{
     YourMethod()
}
catch (Exception ex)
{
     throw
         new Exception("Error");
}
Nikola Davidovic
  • 8,189
  • 1
  • 25
  • 32
0

When you plan to nest your try-catch-block as described by "paul" be aware of the exception type:

using (Entities context = new Entities())      
{          
  try
  {
      try
      {
          context.Office.Add(office);
          retVal = context.SaveChanges();
      }
      catch (DbUpdateException ex)
      {
          SqlException innerException = ex.GetBaseException() as SqlException;
          if (innerException != null && innerException.Number == (int)SQLErrorCode.DUPLICATE_UNIQUE_CONSTRAINT)
          {
              // this exception will be catched too in outer try-catch block <--------
              throw new Exception("Error ocurred");
          }
          //This is momenty where exception is thrown.
          else
          {
              throw ex;
          }
      }
  }
  // Catch (DbUpdateException  ex) if you plan to have the rethrown exception to be catched <------------
  catch (Exception ex)
  {
      throw new Exception("Error");
  }

}

Mcolli
  • 26
  • 2