I've been working on my ASP.NET MVC application for months now. When I first started working on it I was using Entity Framework 4.3 (Code-First w/Migrations). While I was doing so I ran into some problems trying to do updates on my MainClient table. MainClient contains all of a client's basic information, and has a 1:1 relationship with the BPClient table, which contains more specific information about that client pertaining to their license agreement for the BP module. Both of which can be edited on the same page in a tab control. However, I kept on getting the following exception when trying to change the EntityState of the MainClient object to being EntityState.Modified:
System.InvalidOperationException : An object with the same key already exists
in the ObjectStateManager. The ObjectStateManager cannot track multiple objects
with the same key.
I noticed while debugging that the object itself was considered Detached when it went into my Controller class to be saved. As a workaround for this issue, I applied a similar solution to the problems found in this blog post and in this SO question. Here's how the code for re-attaching the objects looked afterwards (messy, I know), given the Edit method being passed in a MainClient object called client
:
var newClientObject = new MainClient { ClientID = client.ClientID };
Db.MainClients.Attach(newClientObject);
Db.Entry(newClientObject).CurrentValues.SetValues(client);
var bpClient = new BPClient { ClientID = client.ClientID, BaseClient = newClientObject };
if (client.BPClient != null)
{
Db.BostonpostClients.Attach(bpClient);
Db.Entry(bpClient).CurrentValues.SetValues(client.BPClient);
}
Db.SaveChanges()
This worked just fine and dandy through all test cases. Up until recently.
Recently, I upgraded my application to use Entity Framework 5 (still using Code-First). When I was testing the MainClient edit page again, though, I found some rather erratic behavior. Some fields, when edited, would be saved without problems. Others would never be committed to the DB. Still others would persist fine, but only if they were the only part of the object being edited. I debugged the heck out of the DbContext that was in the Controller class, and found, rather annoyingly, that not only were the changes made on the page being sent to the Controller class, but that the ObjectStateManager had both the MainClient and BPClient objects in it with the changes that had been made on the page as well! I should mention here, by the way, that I didn't receive one error while debugging it, not even after SaveChanges().
I decided to try and revert the code to what it had been originally, that is to say the logical way of doing it:
Db.Entry<BPClient>(client.BPClient).State = EntityState.Modified;
Db.Entry<MainClient>(client).State = EntityState.Modified;
Db.SaveChanges();
And now it works totally fine. No InvalidOperationException. So that's been solved just fine.
What's still bothering me is trying to figure out just what changed in 5.0 that made my earlier fix stop working and go all wonky on me. Why did that code work fine in 4.3 but not in 5.0? What in 5.0 made committing to the database with that code so erratic?
Does anybody know why this would have happened?