I'm using Entity Framework. I want to load an entity, edit it, and save the changes back in the DB. But no matter if I've edited a foreign key property or a simple property, EF gives me the following error:
Attaching an entity of type 'ClassX' 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.
Please note that ClassX
is not a direct virtual property of the class that I'm trying to update, instead it's a virtual property in some of the other classes that my class has navigation properties to them.
I've read some related issues. But I didn't really get how I should apply them to my own problem, since I'm using a generic repository as posted below.
public class GenericRepository<T> where T : class
{
private EFDbContext context = new EFDbContext();
public IEnumerable<T> GetAll()
{
return context.Set<T>();
}
public void Insert(T entity)
{
context.Set<T>().Add(entity);
context.SaveChanges();
}
public void Update(T entity)
{
context.Entry(entity).State = System.Data.Entity.EntityState.Modified;
context.SaveChanges();
}
//removed for brevity
}
I've encountered another problem related to virtual properties and I was advised to use ViewModels
and Object to Object mapping.
As far as I got it, there's 3 options:
ViewModels
and object-to-object mapping. I'm not going with this one, it was really painful since o2o mapping libraries have lots of bugs.reference
. But I can't do that since the repository is generic. Maybe I should use reflection API for that?Can anyone please explain why this problem happens and what's the easiest way to solve it?
When you set the State
of an entity to Modified
it also attaches all children (entities referenced by navigation properties) with State == EntityState.Unchanged
. If your context already has entities with the same key, it will raise that error.
If you want those entities to be ignored, there are a few options I can think of:
Update
, and don't worry about the children entities because with EntityState.Unchanged
, when you call SaveChanges
, they'll be ignored. This probably doesn't make sense if you're using some kind of Repository Pattern.null
before setting State = EntityState.Modified
State = EntityState.Modified
, for child entities you want to ignore, set State = EntityState.Detached
Edit
It would also be good to figure out why the context would end up with multiple child entities with the same key in the first place.