Why isn’t EF saving changes?
If you’re following an older tutorial for ASP.NET MVC and/or Entity Framework,
but trying to apply it to the latest versions of the same, you may run into a
problem where your controller’s
Edit action doesn’t actually save any edits
to the database.
You probably have something like the following in your
1 2 3 4 5 6 7 8 9 10 11 12 13
When you test this out, you find that the changes you make aren’t actually committed to the database. What’s going on, EF???
An Excursus on Unit of Work
Entity Framework uses a “unit of work” approach to database operations. Thats
basically what all those
Context classes are: they define the tables you need
for a single operation. When you need to do something, you create the context,
do the work, and then end the context after telling EF to
A typical workflow may be:
- Open a context
- Query out one or more objects from the database (like
- Make changes
- Destroy the context
Since EF knows what
Products it instantiated, it can examine them, determine
what changed, and generate the appropriate query to update the corresponding
But this design pattern breaks down when applied within the stateless architecture of a web session. A single unit of work can’t transcend multiple HTTP requests: the server cleans it up after each response is written out.
In idiomatic MVC, the editing of a row operates like this:
- Open context
- Query out
- Render EditView
- Close context
- User edits form
- Open context
- Close context
- Redirect to
Recall the example controller above. The
product parameter is created
externally to Entity Framework. EF did not instantiate the
on a query, rather MVC’s
ModelBinder instantiated the object based on the
POSTed form data. As a result, EF’s
SaveChanges method knows absolutely
nothing about that object instance.
Remember that when the
Product is a newly created product (i.e. the
ProductID is 0), we had to manually inform EF about its exsistance. This was
done by adding the object to the context’s
Products collection. This way EF
knows about the object and can generate the appropriate
INSERT command when
SaveChanges is called.
But what about the case when the
Edit action is called to save changes to an
Product? How do we tell EF to track it?
Say hello to the context’s
This method allows you to view/change the state of a tracked enitity instance. If the instance is not currently tracked, EF will start tracking it.
All we need to do is add an else clause that informs Entity Framework about the
object and sets its state to modified. Thus when
SaveChanges is called, EF
can generate the needed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
ORMs are great, but sometimes the abstraction they provide breaks down in siginifcant ways. When that happens, you often have to dig in and learn how the abstraction actually works so that you can understand and apply the appropriate fixes.
At least this time it wasn’t too difficult.
- Entity States and SaveChanges (msdn.microsoft.com)
- Using DbContext in EF 4.1 Part 4: Add/Attach and EntityStates (blogs.msdn.com)