2

In my ASP.NET MVC 3 application, I use EF 4.2. In my database, I have a unique constraint for a column.

I try to insert same data in order to see what I get but I am getting the below error:

An error occurred while updating the entries. See the inner exception for details.

Inside the inner exception I can see the full error about unique constraint. But how can I uniquely catch this exception to tell the user this:

You are entering the same value again.

Here is what I do currently:

try
{
    UpdateModel<ConditionType>(conditionType, null, null, new string[] { "ConditionTypeId" });
    _conditionTypeRepository.Save();

    return RedirectToAction("conditiontype");
}
catch (Exception ex)
{
    ModelState.AddModelError("", "There was an error while updating: " + ex.Message);
}

But this is a generic approach. What I would like to do is to provide a specific message.

Any thoughts?

Edit:

I tired the below but this time it didn't catch it:

catch (SqlException ex)
{
    if (ex.Number == 2627)
    {
        ModelState.AddModelError("", "You are entering the same value again.");
    }

    ModelState.AddModelError("", "There was an error while updating the value: " + ex.Message);
}

I dug into a little bit and it turned out that it throws an exception type of System.Data.Entity.Infrastructure.DbUpdateException which does not contain the exception number.

EDIT:

Here how I solve the problem but I am sure it is not the best way of solving it. Any idea how to refactor this code?

catch (Exception ex) {

    if (ex.InnerException.InnerException.GetType() == typeof(SqlException)) {

        if (((SqlException)ex.InnerException.InnerException).Number == 2627)
            ModelState.AddModelError("", "You are entering the same value again.");
        else
            ModelState.AddModelError("", "There was an error while updating the value: " + ex.Message);

    } else {
        ModelState.AddModelError("", "There was an error while updating the value: " + ex.Message);
    }
}
tugberk
  • 57,477
  • 67
  • 243
  • 335
  • 1
    In the debug-window click the plus sign, and you'll see the inner exception that occured. – Lasse Edsvik Dec 27 '11 at 13:38
  • 1
    Something similar was already discussed. See if this can help you http://stackoverflow.com/questions/3694359/entity-framework-how-to-properly-handle-exceptions-that-occur-due-to-sql-constr – Pavan Dec 27 '11 at 13:40
  • @LasseEdsvik ok, I will tell the end user to do that. did you read the question carefully? – tugberk Dec 27 '11 at 13:41
  • @JQone I looked at it now. Can you see my update on the question. – tugberk Dec 27 '11 at 13:49
  • @JQone the main problem is that it does not catch `SqlException`. If I try to catch it, it throws the unhanded exception. – tugberk Dec 27 '11 at 14:02
  • @LasseEdsvik sorry for the harsh answer. I understood what you mean now. – tugberk Dec 27 '11 at 14:11

3 Answers3

3

You could do something like this to look for an inner exception that is a SqlException and then handle the sql exception differently.

catch(Exception ex)
{
    Exception current = ex;
    SqlException se = null;
    do
    {
        se = current.InnerException as SqlException;
        current = current.InnerException;
    }
    while (current != null && se == null);

    if (se != null)
    {
        // Do your SqlException processing here
    }
    else
    {
        // Do other exception processing here
    }
}
pstrjds
  • 16,840
  • 6
  • 52
  • 61
1

One could also use the GetBaseException() method as that would get you the root cause exception which is the SqlException.

josagyemang
  • 503
  • 5
  • 9
0

To get the innermost Exception, you could do something like this:

SqlException se = null;
Exception next = ex;

while (next.InnerException != null) 
{
   se = next.InnerException as SqlException;
   next = next.InnerException;
}

if (se != null)
{
    // Do your SqlException processing here
}
else
{
    // Do other exception processing here
}
Designpattern
  • 184
  • 10