In Entity Framework and the repository pattern, where should DB exceptions be handled?

entity-framework error-handling exception repository

Question

How would you implement the repository pattern, Entity Framework 4.1, and Code First in this scenario: The projects listed below are included in the Visual Studio solution.

Solution
|-Web Application Project
|-DAL Project
|-Model Project

There are thus many courses in the Model Project. Let's say there is a class named User with the (simplified) definition as follows:

public class User{

    [Key]
    public int UserId { get; set; }

    ....

    //this property has a unique constraint created in a custom DB Initializer class
    public string email { get; set; }

    ....
}

The repository methods (Insert, Update, etc.) and the Initializer class are located in the DAL project:

public class MyDatabaseInitializer : IDatabaseInitializer<MyDatabase>
{
    public void InitializeDatabase(MyDatabase context)
    {
        try
        {
            if (!context.Database.Exists())
            {
                context.Database.Create();
                context.Database.ExecuteSqlCommand(
                    "ALTER TABLE Users ADD CONSTRAINT uc_Email UNIQUE(Email)");
            }
        }
        catch (Exception ex)
        {
            throw ex.InnerException;
        }
    }
}

My Unit of Work class's Commit function looks like this:

public string Commit()
{
    string errorMessage = string.Empty;

    try
    {
        Database.Commit();
    }
    catch (DbUpdateException updExc)
    {                                 
        errorMessage = updExc.InnerException.Message;            
    }                       

    return errorMessage;
}

As you can see, I manageDbUpdateException in theCommit() This indicates that any class that may result in an update error would be handled in this function of the Unit of Work class.

Let's say the following information is inserted into the User records:

(UserId,....,Email,...)
1, ... , person1@mail.com , ...
2, ... , person1@mail.com , ...

It is evident that a DbUpdateException would result from this. Of course, this is contagious and spreadable to the location where it ought to manifest. This design, in my opinion, is wholly flawed:

  1. Each property should be validated independently; shouldn't the same be true for a field's unique value? Do I have to combine DAL and MODEL into a single project as a result?

  2. How would I deal with problems brought on by a breach of the uniqueness for fields A and B in table A and field C in table C? It's not very clear to use error messages like "The value already exists" or "Uniqueness violation"!

  3. Should I add a new project with a business layer that handles this kind of error handling?

  4. Should I handle the updates' Action/Controller (ASP.NET MVC) error handling?

  5. How should an application that supports many languages handle an error message?

1
8
8/12/2012 8:45:52 AM

Popular Answer

The same thing is happening to me, and I am now processing the exception in my controller.

Think about the following thing:

public class Part
{
    public int Id { get; set; }
    public string Number { get; set; }
}

In the database, I've put up a unique constraint on the "Number" column so that if a duplicate number is entered, an exception will be raised. I'm handling the exception as follows:

[HttpPost]
public ActionResult Create(Part part)
{
    if (ModelState.IsValid)
    {
        try
        {
            db.Parts.Add(part);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        catch (DbUpdateException e)
        {
            SqlException s = e.InnerException.InnerException as SqlException;
            if (s != null && s.Number == 2627)
            {
                ModelState.AddModelError(string.Empty,
                    string.Format("Part number '{0}' already exists.", part.Number));
            }
            else
            {
                ModelState.AddModelError(string.Empty,
                    "An error occured - please contact your system administrator.");
            }
        }
    }
    return View(part);
}

This just causes the user to see a validation error that looks like this and returns them to the same view:

enter image description here

Although I'm unsure of how "appropriate" this is, I can't think of a better way to address this situation right now (for example, even if I caught this in myDbContext derived class and raised a more focused exception. To use it in any way at runtime, I would still need to handle it in the controller.

Also uncertain is if I need to examine the inner exception. I altered the this post's code, which essentially checks for aSqlException Before informing the user of an issue, it looks for it in the inner exceptions and verifies the error number (in this example, 2627, which is a unique key constraint). A generic error message is shown in its place if the SQL error number is anything else.

Update:

In order to manage exceptions outside of the controller, I now handle them in a domain service class that is a derivation of the example provided.

4
5/23/2017 10:32:46 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow