Reputation: 6963
BACKGROUND
I'm having some trouble with updating an entity in EF. I keep getting this error:
"An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key"
I am fully aware that there is obviously another entity somewhere that is attached. However, I currently cannot track it down. There is a lot of code and I've spent quite some time on it already. As far as I can see, I am using the AsNoTracking()
extension method on all my queries.
WHAT I NEED
My question is this: Is there any way I can see what is actually in the ObjectStateManager at any given time? If I can see the items in there during debugging, I can more quickly track down where this is coming from.
If the above is not possible, I would appreciate any advice on how best to tackle this problem.. it's like a needle in a haystack right now.
Upvotes: 7
Views: 2102
Reputation: 11348
Often Overlooked: Context.Set<T>.Local()
which provides ONLY attached entities for the type in question.
Upvotes: 1
Reputation: 150178
Is there any way I can see what is actually in the ObjectStateManager at any given time? If I can see the items in there during debugging, I can more quickly track down where this is coming from.
You can also see what's in the ObjectStateManager by using the Quick Watch feature of the Visual Studio debugger. The path is:
context -> ObjectContext -> ObjectStateManager -> Non-Public members
Upvotes: 6
Reputation: 6963
This question helped:
what is the most reasonable way to find out if entity is attached to dbContext or not?
and I implemented it in this way:
var attachedEntity = context.ChangeTracker.Entries<T>().FirstOrDefault(x => x.Entity.Id == entity.Id);
// If the entity is already attached.
if (attachedEntity != null)
{
// Set new values
attachedEntity.CurrentValues.SetValues(entity);
}
else
{
// Else attach the entity (if needed)
if (context.Entry(entity).State == EntityState.Detached)
{
Entities.Attach(entity);
}
// Set the entity's state to modified
context.Entry(entity).State = EntityState.Modified;
}
context.SaveChanges();
Note: Entities
is just IDbSet<T>
from context.Set<T>()
and the code above is from the Update() method in my generic repository.
Upvotes: 1
Reputation: 14948
This article: http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2007/08/27/9656.aspx contains some code for dumping the contents of an ObjectStateManager
.
From here:
Almost certainly what is happening here is that the object you are trying to delete is not attached, but a related entity or collection loaded on the detached instance is already attached to the ObjectContext. So when you try to attach the entity you are trying to delete, we try to attach the entire graph, which includes entities that are already attached.
This sort of problem is a bit of a pain, so in my case I try to do as much activity as I can within a single using(Context context = new MyEntities())
block as I can.
The other piece of advice would be to check that an object does not already exist before adding it. Kind of obvious, I know, but I have been tripped up by that one a few times in the past.
Upvotes: 0