How to intercept exceptions when working with the Entity Framework?

Asked

Viewed 1,618 times

7

I want to handle errors returned by Entity Framework.

In this example I am forcing the insertion of a duplicate record (Name already existing in the database and the table column is configured as a Unique Index):

[HttpPost]
[ValidateAntiForgeryToken]
[Authorization(Roles = "Editar")]
public ActionResult Gravar(Domain.Cidade obj)
{
    if (ModelState.IsValid)
    {
        try {
            if (new App.Cidade().Gravar(obj))
                return RedirectToAction("Listar");
        }
        catch (SqlException e) {
            TempData["Mensagens"] = "Ocorreu um erro enquanto ...";
        }
        catch (EntitySqlException e) {
            TempData["Mensagens"] = "Ocorreu um erro enquanto ...";
        }
        catch (EntityException e) {
            TempData["Mensagens"] = "Ocorreu um erro enquanto ...";
        }
        catch (Exception e) {
            TempData["Mensagens"] = "Ocorreu um erro enquanto ...";
        }
    }
    return View("Cadastro", obj);
}

Note that I have separated into three basic types of error handling: SqlException, EntitySqlException and the System.Exception.

But the exception returned is always falling into treatment for System.Exception.

My record method:

public bool Gravar(Domain.Cidade obj)
{
    var record = context.Cidades.SingleOrDefault(x => x.Id == obj.Id);
    if (record == null)
        context.Cidades.Add(obj);
    else
        context.Entry(record).CurrentValues.SetValues(obj);

    context.SaveChanges();
    return true;
}

How do I get the correct return of the Exception type?

3 answers

6

I will give you an answer that does not directly answer what you want but will help you and others to other problems with exceptions.

First we start by conceptualizing things correctly.

But the exception returned is always falling into treatment for System.Exception

An exception is not returned, it is thrown. It may seem silly but conceptualizing correctly helps to understand the problem and find a solution.

An exception cannot be accessed without it being explicitly captured through a catch. So let’s redo the sentence:

The exception captured is always System.Exception and not one more specific

If you want to capture a more specific exception, why are you capturing the most general exception of all?

I do not know the EF well but according to another answer it seems that you are wanting to capture the DbUpdateException. And you could have discovered this on your own.

There are two requirements for a programmer to use one catch:

  • know which exception you want to capture
  • manage to do something useful with the exception, possibly recovering the situation.

Apart from the use in one of the first methods executed (first levels, maybe the Main) and basically to log in failure, is almost 100% sure that capture the Exception is a mistake.

  • Why do you want to specifically capture a Exception? To say that it’s because you don’t know what the correct exception is exactly the best argument for nay capture her.
  • And what can you do to recover from any indefinite exception? Most likely nothing.

When the program captures a more general exception it is hiding a problem rather than solving it. Abuse of try/catch seems to be a trend, especially the capture of Exception. For some reason programmers have adopted the belief that the more catch exists in the program, less bugs it will have. And it is exactly the opposite that occurs. I will repeat: capture a general exception prevents the program from solving a specific problem.

In your trouble you tried to capture SqlException, EntitySqlException, EntityException, and they were not released, so another exception was thrown and as any exception is derived from Exception, fell there.

Start solving the problem taking this catch and let the program break, then you will know what was the exception that caused the problem.

You can until being surprised and discovering that the problem was somewhere else you didn’t imagine, that it was a programming error, or that it was lack of memory (which can occur even having enough memory, but this is another matter). You simply don’t know what is causing the problem and are capturing a flaw possibly unrelated to what you are doing.

Let’s see if you understand what I wrote: after you discover the correct exception, you should put the section below back in the program?

catch (Exception e) {
    TempData["Mensagens"] = "Ocorreu um erro enquanto ...";

I put in the Github for future reference.

I tried to show you how to find the solution on your own, so you can manage in other situations. To better understand the operation of exceptions I have answered elsewhere: It is good practice to make an exception in such cases? and Best way to deal with Exceptions.

  • 4

    I understood all this you are talking about. I like to give answers that are the fishing rod. How you go fishing is a matter of each. Nothing caused me trouble, I just wanted to help everyone because this is a relatively basic resource that there is the worst understanding in programming nowadays. I’m not complaining about your code, because I won’t work with it. This other question quoted would make an interesting post. Everyone learns that it is better to throw an exception than return an error code.There shows that error code is not the problem. The problem is the returns instead of launch.

  • 3

    @Tremdoido I did the following put this question in the META: http://meta.pt.stackoverflow.com/q/1531/6026

  • 4

    @On the other, I couldn’t find a way to answer it the way I like it without completely falling out of its scope. In this one I have found a way to be an answer to your question. There is serving more as an example that had Error code is not a problem, but there is no explanation, because it is not your doubt. I like to help as many people as possible but I can’t help but answer in some way by giving some way to solve the problem of the specific question. If an opportunity arises that fits a better explanation of error codes generically, I post something.

  • 1

    @Tremdoido tried to give an answer that helps in the other matter. It is not directly linked, but was inspired by: http://answall.com/questions/21767/por-que-devemos-evitar-retornar-c%C3%b3digos-de-error

4

3

You can intercept any and all exceptions in your Controller common implementing a override for the following method:

protected override void OnException(ExceptionContext filterContext)
{
    /* A exceção fica em filterContext.Exception */
    /* Os detalhes da execução ficam em filterContext.Exception.StackTrace */
}

If you just want to intercept Entity Framework exceptions, follow the script of this answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.