An Object with the Same Key Already Exists in the Objectstatemanager. the Objectstatemanager Cannot Track Multiple Objects with the Same Key

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key

Edit: Original answer used Find instead of Local.SingleOrDefault. It worked in combination with @Juan's Save method but it could cause unnecessary queries to database and else part was probably never executed (executing the else part would cause exception because Find already queried the database and hadn't found the entity so it could not be updated). Thanks to @BenSwayne for finding the issue.

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:

public override void Update(T entity) where T : IEntity {
if (entity == null) {
throw new ArgumentException("Cannot add a null entity.");
}

var entry = _context.Entry<T>(entity);

if (entry.State == EntityState.Detached) {
var set = _context.Set<T>();
T attachedEntity = set.Local.SingleOrDefault(e => e.Id == entity.Id); // You need to have access to key

if (attachedEntity != null) {
var attachedEntry = _context.Entry(attachedEntity);
attachedEntry.CurrentValues.SetValues(entity);
} else {
entry.State = EntityState.Modified; // This should attach entity
}
}
}

As you can see the main issue is that SingleOrDefault method needs to know the key to find the entity. You can create simple interface exposing the key (IEntity in my example) and implement it in all your entities you want to process this way.

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key

As mentioned by @anon you can't attach model once you loaded the entity with the same key. The changes must be applied to attached entity. Instead of this:

db.Entry(model).State = EntityState.Modified;

use this:

db.Entry(v).CurrentValues.SetValues(model);

Multiple objects with the same key error

The problem seems originated from EntityState.Modified before SaveChanges method, assuming hiringfactor is new entity as modification target:

db.Entry(hiringfactor).State = EntityState.Modified;

By convention, you can't re-attach a model once the entity has been loaded by the same key value. Try using this code right before SaveChanges:

db.Entry(parentFactor).CurrentValues.SetValues(hiringfactor);

Another way to set modified entity is using AsNoTracking when doing Find method like this:

HiringFactor parentFactor = db.HiringFactors.AsNoTracking().Find(parentId);

Similar issues:

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key

If you load the entity from the context you cannot attach an entity with the same key again. The first entity is still kept in internal context cache and context can hold only one instance with given key value per type (it is called identity map and I described it here in other situation).

You can solve it by detaching former instance but you don't have to. If you only need to save new values you can use this:

  • ObjectContext API: context.YourEntitySet.ApplyCurrentValues(newEntity);
  • DbContext API: context.Entry(oldEntity).CurrentValues.SetValues(newEntity);

Best Practice for Solve An object with the same key already exists in the ObjectStateManager Error

You've got the code to find the entity although you should note that .Local will only work if the entity has been previously fetched from the database or attached elsewhere in the current session.

var attachedEntity = leitner.Set<Person>().SingleOrDefault(x => x.Id == 3);

There's the Remove method on DbSet

leitner.Set<Person>().Remove(attachedEntity);

And the SetValues method on the DbEntityEntry<Person> that is returned from leitner.Entry(attachedEntity)

var p2 = new Person() // for update
{
Id = 3,
Name = "W",
Family = "W",
Age = 90
};
leitner.Entry(attachedEntity).Currentvalues.SetValues(p2);

{An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.}

This exception means that there is a duplicate entity with the same key already tracked by the context. Each entity can be tracked by the context only once. If you try to attach another instance of the same entity (it has the same key as already tracked instance) you will get this exception.

It means that another instance of the entity you are trying to update is already tracked by the context. Because attaching or adding is always applied on the whole object graph (it is applied on related entities accessed through navigation properties as well) the problematic entity doesn't have to necessarily be the one you are trying to modify but any of its relations.

You can try to use dbContext.ChangeTracker.Entries<T>().FirstOrDefault(e => e.Id == entity.Id) to check if entity instance with the same key is already tracked.

The ObjectStateManager cannot track multiple objects with the same key

there are multiple problems;

  • Do not call GetAll() if you want to fetch a single entity, what if you have thousands of entities in the database. Just implement a SingleOrDefault in the repository.

Use :

User testUser = userRepository.FirstOrDefault(x => x.Name.Equals(user.Name));

instead of :

User testUser = userRepository.GetAll().FirstOrDefault(x => x.Name.Equals(user.Name));
  • After fetching an existing user from database, just update this item using new values instead of trying to persist the one returned from page;

use

User tempUser = userRepository.GetAll().First(x => x.ID == user.ID);
tempUser.UserName = user.UserName;
....
SaveChanges();

instead of trying to persist user retrieved from page.

  • you need to decide the key of your entity; is it name, is it Id or both.

Error : An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key

I can only imagine that this error occurs if SelectedPatient contains referenced objects of type MasterPatientHaemogram and these again referenced objects of type Haemogram. When you attach SelectedPatient (which is apparently a detached entity) the whole object graph will be attached including Haemogram objects with possibly the same key that you already have loaded in the query for HaemogramsCorrespondingToPatient. This would cause the exception.

Simplest and safest solution is not to try to attach the detached SelectedPatient at all but load a copy from the database and delete this entity instead:

//...
var patient = db.Patients.Find(SelectedPatient.PatientID);
db.Patients.Remove(patient);
db.SaveChanges();

If you dislike to query the database with Find create a stub entity with just the correct key:

//...
var patient = new Patient { PatientID = SelectedPatient.PatientID };
db.Patients.Attach(patient);
db.Patients.Remove(patient);
db.SaveChanges();


Related Topics



Leave a reply



Submit