I have a situation where I have an object that is loaded back from a form to MVC controller via an action. We do not use FormCollection, but the one that use directly the class.
[HttpPost]
public ActionResult AjaxUpdate(Customer customer) { ...
The Customer object contain an object called customer which seem to be updated but when using SaveDatabase() on the context simply doesn’t work.
To make it works I had to use in the action:
myDbContext.Customers.Attach(customer)
//...Code here that set to the customer.SubObject a real object from the database so I am sure that the SubObject contain an id which is valid and the datacontext is aware of it...
myDbContext.Entry(customer).State = EntityState.Modified;
Still, I had an exception concerning the “Store update, insert, or delete statement affected an unexpected number of rows (0)” that I were able to remove by using:
Database.ObjectContext().Refresh(RefreshMode.ClientWins,customer);
So, to warp up my question, why do I have to Attach + change the state + call Refresh. Isn’t there a better way to update an object that contain object that are referenced in an other table. I am using Code first Entity Framework (Poco object). Also, I do not like to use Refresh since it’s hidden from my Databasecontext.
I’ve made a console test project with EF 4.3.1. The code is my guess what you mean with the commented line and your comments below the question (but my guess is probably wrong because the program doesn’t reproduce your error):
You can copy the code into program.cs and add a reference to EF 4.3.1:
This works without exception. The question is: What is different in your code which could cause the error?
Edit
To your comment that you don’t have a foreign key property
SubObjectIdin the customer class: If I remove the property in the example program above I can reproduce the error.The solution is to load the original subobject from the database before you change the relationship:
Without a foreign key property you have an Independent Association which requires that the object including all references must represent the state in the database before you change it. If you don’t set the reference of
SubObjectincustomerEF assumes that the original state in the database is that customer does not refer to any subobject. The generated SQL for the UPDATE statement contains a WHERE clause like this:If the customer has a subobject in the DB
[SubObject_Id]is not NULL, the condition is not fulfilled and the UPDATE does not happen (or happens for the “unexpected number of rows 0”).The problem does not occur if you have a foreign key property (Foreign Key Association): The WHERE clause in this case is only:
So, it doesn’t matter what’s the original value of
SubObjectand ofSubObjectId. You can leave the valuesnulland the UPDATE works nonetheless.Hence, the alternative solution to loading the original subobject is to introduce a foreign key property in
Customer:Or, in case the relationship is not required: