I’m having a rather strange issue with Entity Framework 4.3 in my MVC application. I’m using a Unit of Work wrapper around DbContext, and in my MVC application I use Unity to pass this UOW to my repositories, and repositories to controllers. I’ve registered the UOW type with the HierarchicalLifetimeManager.
When I try to persist an entity to the database that raises an error, e.g. the database throws a UNIQUE constraint violation, the entity is kept inside EF’s ObjectStateManager. So when I go back in my application to fix the error and save the new entity (without errors), EF first tries to add the old and invalid object again, thus failing with the same error.
What am I missing here? I believe that the invalid object should be completely forgotten by EF and that this would be done automatically. But it’s clearly not the case.
To add objects to DbContext in order to persis them, the following command gets called (where base is the DbContext):
base.Set<TEntity>().Add(objectToPersist);
And to commit the changes to the database, I call:
base.SaveChanges();
Which throws the error.
Right, that’s not the case and I’ve never heard that entities would be detached from the context automatically when an exception occured.
There are basically two options to deal with the problem. I show a simple model with your example of a unique key constraint violation:
The above is the prefered solution: Correct the object which is attached to the context.
If you need – for whatever reason – to create a new object you must detach the old object from the context. That object is still in state
Addedand EF will try to save the object again when you callSaveChangesleading to the same exception as before.Detaching the old object would look like this:
This procedure can be tricky if relationships are involved. For example if
customerhas a relationship to a list of orders, detaching thecustomerobject will delete references between customer and its orders if the orders are attached to the context as well. You have to reestablish the relationships with the newcustomer2.Therefore I’d prefer to modify the attached object to put it into correct state. Or let the application crash because such constraint violations usually indicate bugs in the code or – in a multiuser environment – should be handled with proper optimistic concurrency checks.