1

In my MVC application, I have been using Repository pattern for DAL.

Now, when I do select one entity record and and update the entity field value and do Update operation then getting below error.

Attaching an entity of type 'DAL.User' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate."} System.Exception

Below is repository stuff:

public void Update(TEntity entity)
{
    if (_context.Entry(entity).State != EntityState.Modified)
    {
         _dbSet.Attach(entity);
        _context.Entry(entity).State = EntityState.Modified;
    }
}

Calling as follow: In Bussines layer library: Manager class :

    private readonly IUnitOfWork _unitOfWork;
    private IRepository <User , int> UserRepository
    {
        get
        {
            return _unitOfWork.GetRepository<AccountUser, int>();
        }
    }
    public void UpdateUserEntity(UserDTO u)
    {
        try
        {

            User model = new User ();
            UserRepository.Update(Mapper.Map(u, model));
            _unitOfWork.SaveChanges();
        }
        catch (Exception ex)
        {
            throw;
        }
    }

Please guide me how I could resolve above error.

tereško
  • 58,060
  • 25
  • 98
  • 150
user3711357
  • 1,425
  • 7
  • 32
  • 54
  • Where is the Tentity argument for the Update() method coming from? Is it an object that you read from the database, modified , and are now trying to save back to the database? Or is it an model object that was created by posting data to some web endpoint in your application? – Tanuj Mathur Sep 03 '14 at 05:35
  • Please find udated question with manager layer stuff. – user3711357 Sep 03 '14 at 05:46
  • You might have a look at my answer on [ASP.NET MVC - Attaching an entity of type 'MODELNAME' failed because another entity of the same type already has the same primary key value](http://stackoverflow.com/questions/23201907/asp-net-mvc-attaching-an-entity-of-type-modelname-failed-because-another-ent/39557606#39557606). – Murat Yıldız Sep 18 '16 at 12:36

2 Answers2

4

The exception says that there is another entity with the same key that has been attached, but different reference.

  • The exception could be caused by previous attached entity.

    db.Set<Entity>().Attach(new Entity { Id = 123 });
    db.Set<Entity>().Attach(new Entity { Id = 123 }); // different reference but same key
    
  • Or could be also caused by tracked entity that automatically attached.

    db.Set<Entity>().FirstOrDefault(e => e.Id == 123); // automatically attached
    db.Set<Entity>().Attach(new Entity { Id = 123 }); // different reference but same key
    

The second cause can be solved by mentioning AsNoTracking when retrieving item.

db.Set<Entity>().AsNoTracking().FirstOrDefault(e => e.Id == 123);

Or to be safe you can use this extension to always detach any attached entity.

public static class DbSetExtension
{
    public static void SafeAttach<T>(
        this DbContext context, 
        T entity, 
        Func<T, object> keyFn) where T : class
    {
        var existing = context.Set<T>().Local
            .FirstOrDefault(x => Equals(keyFn(x), keyFn(entity)));
        if (existing != null)
            context.Entry(existing).State = EntityState.Detached;

        context.Set<T>().Attach(entity);
    }
}

Usage.

db.SafeAttach(entity, e => e.Id);
Nelson Reis
  • 4,780
  • 9
  • 43
  • 61
Yuliam Chandra
  • 14,494
  • 12
  • 52
  • 67
  • do you have any comment on even if existing entity's state changed to detached, attaching the new one still throws error. – Okan Kocyigit Jan 26 '18 at 08:45
  • AsNoTracking solved my problem. that's really wonderful, i was wondering why when i fetch it from DBContex and modify the object and then attach the modified object, it threw me exception as that was the first time i had attached that entity as per my understanding. But i was wrong and not knowing about the self tracking mechanism of the Entity Framework. Thanks! – Mantra Jan 22 '20 at 07:18
0

It's because of the reason, "TEntity entity as a new object instead of the one which already exists". Means,Entity framework treats each new object as new entry.(eventhough with same existing old data,PK & all).

Solution is,

First retrieve the object from database

Do/assign the changes to the same object (preferably without changing Primary key)

Then do state as Modified ,Update,SaveChange()

Community
  • 1
  • 1
  • Its already there as i do first retrieve and then populate on ui and ui will update the values and then calling update method which throws above expceiton. Please check updated quesiton with manage layer stuff. – user3711357 Sep 03 '14 at 05:45