Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating existing data in EF 6 throws exception - "...entity of the same type already has the same primary key value."

I am trying to update a record using Entity Framework 6, code-first, no fluent mapping or a tool like Automapper.

The entity(Employee) has other composite properties associated with it like Addreess(collection), Department

It is also inherited from a base called User

The save method is as follows, with _dbContext being the DbConext implementation

        public bool UpdateEmployee(Employee employee)
        {
            var entity = _dbContext.Employees.Where(c => c.Id == employee.Id).AsQueryable().FirstOrDefault();
            if (entity == null)
            {
                _dbContext.Employees.Add(employee);
            }
            else
            {
                _dbContext.Entry(employee).State = EntityState.Modified; // <- Exception raised here
                _dbContext.Employees.Attach(employee);

            }

            return _dbContext.SaveChanges() > 0;

        }

I keep getting the error:

Attaching an entity of type 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.

I have tried the following:

  1. Attaching before setting to EntityState.Modified
  2. Adding AsNoTracking() on querying if the object exists(No exception but DB is not updated) - https://stackoverflow.com/a/23228001/919426
  3. Saving using the base entity _dbContext.Users instead of the Employee entity - https://stackoverflow.com/a/25575634/919426

None of which is working for me now.

What could I have gotten wrong for some of those solutions not to work in my situation?

like image 409
user919426 Avatar asked Jun 07 '15 07:06

user919426


2 Answers

EF already includes a way to map properties without resorting to Automapper, assuming you do not have navigation properties to update:

public bool UpdateEmployee(Employee employee)
    {
        var entity = _dbContext.Employees.Where(c => c.Id == employee.Id).AsQueryable().FirstOrDefault();
        if (entity == null)
        {
            _dbContext.Employees.Add(employee);
        }
        else
        {
            _dbContext.Entry(entity).CurrentValues.SetValues(employee);              
        }

        return _dbContext.SaveChanges() > 0;

    }

This usually generates a better SQL statement since it will only update the properties that have changed.

If you still want to use the original method, you'll get rid of entity from the context, either using AsNoTracking (not sure why it didn't update in your case, it should have no effect, so the problem might be something else) or as modifying your query to prevent it from materializing the entity in the first place, using something like bool exists = dbContext.Employees.Any(c => c.Id == employee.Id) for example.

like image 132
ESG Avatar answered Sep 23 '22 03:09

ESG


This worked for myself

var aExists = _db.Model.Find(newOrOldOne.id);
if(aExists==null)
{
    _db.Model.Add(newOrOldOne);
}
else
{
    _db.Entry(aExists).State = EntityState.Detached;
    _db.Entry(newOrOldOne).State = EntityState.Modified;
}
like image 27
bRySaGeeK Avatar answered Sep 26 '22 03:09

bRySaGeeK