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

I am programming an MVC 4 web application using the first EF 5 database. I have some seemingly trivial problems for which I cannot find the right solution. These issues are related to the object state manager.

In the simplest scenario, everything works fine: I read the entities from the database using Find, put them into the view, wait for a response, restore the entity, write it back using Attach, EntityState.Modified and SaveChanges. Problems arise if, while processing the request, I again get the object from the database.

I do this if:
1. For some reason, I want to check some values ​​of the original object.
2. Some of my values ​​are not subject to change, as they identify the object. I put them in my opinion for reference only, using DisplayFor. Of course, the reconstructed model does not have these values. I get the source object from the database, and in the controller use TryUpdateModel to combine it with the model from the view.

When I call Attach, I get the exception "An object with the same key already exists in the ObjectStateManager. An 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 object with a specific key. I would like to make the one I want to keep, replace the one that is present, if at all. I would like it to be automatic, that is, without me, to say if there is another one that needs to be replaced.

Is there any way to achieve this?

+4
source share
1 answer

At the same time, I started using the Model First approach, so I'm not quite sure that the following applies: I think some of them might be useful.

  • Run queries using someContext.someDbSet.AsNoTracking() if you just want to find some data but are not going to update the database with the changes. See AsNoTracking on MSDN.
  • Exclude updating some properties of the model. This will help you update, for example, a user profile without updating a 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 will notice that the somePropertyToIgore field is not specified in the SET clause.

+1
source

All Articles