Reputation: 1469
I am using the following method of trying to update an object using entity framework:
public static void UpdateItem(Item updatedObject) {
using (var context = new DbContext())
{
context.MyObjectsPropertys.Attach(updatedObject);
context.Entry(updatedObject).State = EntityState.Modified;
context.SaveChanges();
}
}
I get an error on the attach:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
If I try to change the Attach call to an Add call (object with same key already exists objectstatemanager) I get:
Cannot insert duplicate key in object 'database.Table'. The duplicate key value is (AttributeValue). The statement has been terminated.
I have found lots of questions regarding this error, but none of the answers work in my situation:
I tried deleting the "Attach" statement as well, and just doing the state change as suggested in Error multiple objects with the same key DbContext, but that didn't work either.
The most frustrating thing to me on this is that this is the exact same sequence of statements that successfully updates other things in the solution.
Upvotes: 0
Views: 3729
Reputation: 3257
Here is how I handle it:
public virtual void Update(TEntity entityToUpdate)
{
if (_db.Entry(entityToUpdate).State == EntityState.Added)
return; // just been added leave state as added
try
{
_dbSet.Attach(entityToUpdate);
}
catch (InvalidOperationException ex)
{
var trackedEntity = _dbSet.Find(GetKeyValues(entityToUpdate));
if (trackedEntity == null)
throw;
if (_db.Entry(trackedEntity).State != EntityState.Unchanged)
throw;
_db.Entry(trackedEntity).State = EntityState.Detached;
_dbSet.Attach(entityToUpdate);
}
_db.Entry(entityToUpdate).State = EntityState.Modified;
}
public object[] GetKeyValues(TEntity entity)
{
var objectContextAdapter = ((IObjectContextAdapter)_db);
var name = typeof(TEntity).Name;
var entityKey = objectContextAdapter.ObjectContext.CreateEntityKey(name, entity);
var result = entityKey.EntityKeyValues.Select(kv => kv.Value).ToArray();
return result;
}
Upvotes: 0
Reputation: 11544
You must check if an entity with the same key is already tracked by the context and modify that entity instead of attaching the current one:
var trackedEntity = context.MyObjectsPropertys.Find(updatedObject.Id);
context.Entry(trackedEntity).CurrentValues.SetValues(updatedObject);
context.Entry(trackedEntity).State = EntityState.Modified;
context.SaveChanges();
Upvotes: 5
Reputation: 12705
you must be retrieving the same object and since then the object retrieved is being tracked by the DataContext object. Adding would certainly give an error because the key obviously is present in the dictionary.
I think you can retrieve the local entities using context.ChangeTracker.Entries()
and then look for the same key if present
Upvotes: 1