0

I thought I had this all figured out, but I'm hitting a brick wall.

Client sends in an object, my controller checks if user has right to edit, then proceeds to update the entity in the database. (along with any navigational property the object has).
My problem is, that I can't seem to get it work...

I tried

var obj = context.Recipes.SingleOrDefault(o=>o.ID == id);
UpdateModel(obj);

But I got a "model cannot be updated" exception.
So I tried a different approach, putting Recipe r into the parameter list (and let the model binder do the work) and call

context.Recipes.Attach(r); 

but that leaves things on "Unchanged", so context.SaveChanges() does nothing.

Is there a simple solution without me having to write obj.SomeProperty = r.SomeProperty for EVERY property on my object?

Bonus question: if my entity has a navigational property (collection) I obviously add the new ones sent in (with ID == 0), but how do I know which one to delete? Can I leverage EF's Change Tracking somewhere here?

For both questions: should there be a magic "compare this object with this object, and then save" method?

TDaver
  • 7,164
  • 5
  • 47
  • 94

3 Answers3

3

Answer for your question is very unpopular. EF doesn't have any support for this. EF can synchronize only state of simple object without navigation properties. Once you have to synchronize changes in relations like added or removed related entity you must do it completely manually - especially deletes require this or you must set deleted relations in separate collection from the client and replicate deletion on attached entity which is quite cumbersome.

As a workaround people use TryUpdateModel or UpdateModel from MVC which performs changes in navigation properties but in such case you cannot place any other demands on update procedure. Simple old values will be overwritten with new values coming from your client.

EF code first has equivalent to ApplyOriginalValues:

context.Entry(attachedEntity).OriginalValues.SetValues(detachedEntity);
Community
  • 1
  • 1
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
2

For your question about handling navigation property updates, see the Adding Course Assignments to the Instructor Edit Page section of this tutorial:

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/updating-related-data-with-the-entity-framework-in-an-asp-net-mvc-application

tdykstra
  • 5,880
  • 2
  • 23
  • 20
1

Try using EntityState in place of Update model like following and see if it helps

context.Entry(obj).State = EntityState.Modified;
db.SaveChanges();
Pankaj Upadhyay
  • 12,966
  • 24
  • 73
  • 104
  • half-great. There are some properties (like "Created") that do not need to be updated. Is there an "ApplyOriginalValues" like method in CodeFirst? Would that help? – TDaver Jan 15 '12 at 11:45
  • I am not sure there is anything like dat...There is one thing you can do in this regard though....Load the original object by calling `var originalItem = yourContext.YourModel.Find(id)` and then replace the value of fields such as "Created" by using `modifiedObj.Created = originalItem.Created` ....And finally call the EntityState.Modified – Pankaj Upadhyay Jan 15 '12 at 12:00
  • I can't load the object, while I'm trying to Attach another copy of the entity to the context. That's an exception. :( – TDaver Jan 15 '12 at 13:03