How can I replace an entity by another entity with the same key in an Entity Framework DB first approach?

StackOverflow https://stackoverflow.com/questions/15837526

  •  01-04-2022
  •  | 
  •  

문제

I am programming an MVC 4 webapplication using EF 5 Database first. I have some apparently trivial issues for which I cannot find a proper solution. These issues are with the object state manager.

In the simplest scenario, everything works fine: I read entities from the database using Find, put them in a view, wait for a response, reconstitute the entity, write it back using Attach, EntityState.Modified and SaveChanges. Problems occur if, while processing a request, I get the entity from the database once more.

I do this if:
1. I want to check some values of the original entity for some reason.
2. Some of my values are not to be modified, because they identify the entity. I put these in my view for reference only, using DisplayFor. Of course, the reconstituted model does not have these values. I get the original entity from the database and in the controller use TryUpdateModel to merge it with the model from the view.

When calling Attach, I get an exception "An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.".

If I use Context.Entry(t).CurrentValues.SetValues(t); instead of DbSet.Attach(t);, I get the following exception:

Member 'CurrentValues' cannot be called for the entity of type 'Price' because the entity does not exist in the context. To add an entity to the context call the Add or Attach method of DbSet<Price>.

As I understand it, there are two instances of an entity with the specific key. I would like to make the one I want to save, replace the one present, if at all. I would like this to be automatic, that is, without me having to tell if another one is present already that has to be replaced.

Is there a way to achieve this?

도움이 되었습니까?

해결책

In the mean time, I've started using the Model First Approach, so I am not quite sure if the following applies, but I think some of it might be useful.

  1. Run queries using someContext.someDbSet.AsNoTracking(), if you just want to look up some data, but do not intend to update the database with changes. See AsNoTracking on MSDN.
  2. Exclude some model properties from being updated. This will help you to update e.g. a user profile, without updating the hashed password, stored in the same model.

    someContext.someDbSet.Attach(someModelInstance);
    var entry = substanceContext.Entry(someModelInstance);
    entry.State = EntityState.Modified;
    entry.Property("somePropertyToIgnore").IsModified = false;
    substanceContext.SaveChanges();
    

If you looked at the SQL generated in the second solution, you would notice that the field somePropertyToIgore is left out from the SET clause.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top