Reputation: 5690
I've been stuck with this problem for over a week now. Hopefully some one can point me in the right direction.
I start with a brief description of my schema.
Asset 1--->1 Address *-->1 Area *-->1 Region *-->1 Country
Package 1-->* Asset
Using Self Tracking Entity (STE) + WCF.
Steps:
In step 2, the call uses eager loading of Addresses.
from p in context.Assets.Include("Address.Area.Region.Country")
This is the error when attempting to call
context.Packages.ApplyChanges(package)
AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.
EDIT
After snooping around, i found that this is a STE issue. The problem being you cannot persist a graph that contains multiple instances of the same entity as outlined here. Here is my question.
How can I add an entity to my entity collection. The new entity may have related entities that contain the same key as one already in the collection. I.e. Add a new asset that may contain the same address, area, region or country entity.
Here are my constrains:
I am aware of the possible solutions suggested by Diego B Vega, but those are not options i can use for my solution. Has anyone any other ideas?
Upvotes: 12
Views: 19683
Reputation: 1926
I was getting this error because I was deleting the records of an entity, reseeding it and then refilling the entity with new data.
As self tracking was enabled on this entity, it did not allow adding the record with the same key, even though a record with that key had been deleted earlier.
Since I did not need self tracking in this situation, I disabled it as:
dbcontext.entity.MergeOption = System.Data.Objects.MergeOption.NoTracking;
Upvotes: 1
Reputation: 24535
I solved this by Setting the resetting the Foreign Key Ids, which required setting the Navigation value to null, before saving.
...something like this:
var countryToId = address.CountryToId;
var countryFromId = address.CountryFromId;
documentAddress.CountryTo = null;
documentAddress.CountryFrom = null;
documentAddress.CountryToId = countryToId;
documentAddress.CountryFromId = countryFromId;
Upvotes: 1
Reputation: 6476
FYI, I wrote a blog post with some additional suggestions to what I had already responded in the EF Forums. Here is the blog post.
Upvotes: 8
Reputation: 31
I encountered the same issue and finally came up with a solution. The basic idea is to prevent certain navigational class type from attaching to the ObjectContext. Here is what I did:
public static void CustomApplyChanges(this ObjectContext context, string entitySetName, TEntity entity, Type[] excludeTypes) where TEntity : IObjectWithChangeTracker
region Handle Initial Entity State
foreach (IObjectWithChangeTracker changedEntity in entityIndex.AllEntities.Where(x => x.ChangeTracker.State == ObjectState.Deleted && !excludeTypes.Contains(x.GetType()))) { HandleDeletedEntity(context, entityIndex, allRelationships, changedEntity); }
foreach (IObjectWithChangeTracker changedEntity in entityIndex.AllEntities.Where(x => x.ChangeTracker.State != ObjectState.Deleted && !excludeTypes.Contains(x.GetType()))) { HandleEntity(context, entityIndex, allRelationships, changedEntity); }
endregion
Type[] excludeTypes = { typeof(Asset), typeof(Address), typeof(Region)};
rep.Entities.CustomApplyChanges(entity, excludeTypes); var changedEntry = rep.Context.ObjectStateManager.GetObjectStateEntries>(System.Data.EntityState.Added | System.Data.EntityState.Modified | System.Data.EntityState.Deleted); foreach (var e in changedEntry) { if (excludeTypes.Any(c => c == e.Entity.GetType())) { rep.Context.Detach(e.Entity); //detach unchanged objects } }
Upvotes: 3
Reputation: 4772
Have you considered just giving up on ORM-s and going back to normal access, if you know what I mean :-)
Not kidding - by the time you wrestle with one single issue like that one (which smells like ORM bug more than anything else) you could have rolled out your own 5-10 functions to do normal sproc calls and easier data type conversion and then you are back to being in full control and and not stuck by libraries which are going to take another like 5yr to stabilize.
Especially since you seem to have very clean schema - meaning quite simple queries and straight forward updates.
Upvotes: 8