Search code examples
c#silverlightwcf-ria-services

Unexpected "An entity with the same identity already exists in this EntitySet"?


I'm getting the error when attempting to add to a client-side EntitySet. The following code intermittently fails on the Add method.

// On the DB side this has a primary key field of IDENTITY(1,1) called Id
var map = new EpisodeDictionaryMap();
map.DictionaryName = dictionary; // String
map.Section = section; // String
map.DictionaryVersion = version; // Int32

episode.EpisodeDictionaryMap.Add(map);

I'm also calling Clear() on the EntitySets for Episode and EpisodeDictionaryMap (amongst others) not before every call to this code, but every now and again, when the user changes to a different screen within the app. This is a recent change, so could be part of the problem.

Upon investigating the DomainContext's EpisodeDictionaryMap collection it would appear that sometimes there are in fact multiple 'New' EpisodeDictionaryMap instances, each with an Id of 0, as I would expect prior to saving, and in these instances the save completes without issue, and the correct Ids are assigned to the client-side entities.

Given that it doesn't seem to be an issue to have multiple entries with an Id of 0 in the EntitySet at any one time (at least whilst they're in a "New" state), I don't understand what the error message is trying to tell me.

I've noticed on some related SO questions that Composition can be an issue, however I'm not using it. With the exception of the Episode reference itself there are also no other foreign key references, which also appears to sometimes cause this error.

Suggestions, thoughts? Many thanks!

Edit:

Full exception (no inner exception exists)

System.InvalidOperationException occurred
    Message=An entity with the same identity already exists in this EntitySet.
StackTrace:
    at System.ServiceModel.DomainServices.Client.EntitySet.AddInternal(Entity entity)
    at System.ServiceModel.DomainServices.Client.EntitySet.<Add>b__5(EntitySet l, Entity e)
    at System.ServiceModel.DomainServices.Client.EntitySet.AddAttachInferrer.Visit(Entity entity)
    at System.ServiceModel.DomainServices.Client.EntitySet.AddAttachInferrer.VisitEntityCollection(IEntityCollection entityCollection, PropertyInfo propertyInfo)
    at System.ServiceModel.DomainServices.Client.EntityVisitor.Visit(Entity entity)
    at System.ServiceModel.DomainServices.Client.EntitySet.AddAttachInferrer.Visit(Entity entity)
    at System.ServiceModel.DomainServices.Client.EntitySet.AddAttachInferrer.VisitEntityRef(IEntityRef entityRef, Entity parent, PropertyInfo propertyInfo)
    at System.ServiceModel.DomainServices.Client.EntityVisitor.Visit(Entity entity)
    at System.ServiceModel.DomainServices.Client.EntitySet.AddAttachInferrer.Visit(Entity entity)
    at System.ServiceModel.DomainServices.Client.EntitySet.AddAttachInferrer.VisitEntityRef(IEntityRef entityRef, Entity parent, PropertyInfo propertyInfo)
    at System.ServiceModel.DomainServices.Client.EntityVisitor.Visit(Entity entity)
    at System.ServiceModel.DomainServices.Client.EntitySet.AddAttachInferrer.Visit(Entity entity)
    at System.ServiceModel.DomainServices.Client.EntitySet.AddAttachInferrer.Infer(EntityContainer container, Entity entity, Action`2 action)
    at System.ServiceModel.DomainServices.Client.EntitySet.Add(Entity entity)
    at System.ServiceModel.DomainServices.Client.EntityCollection`1.Add(TEntity entity)
    at TangoSoft.Client.EpisodeExtensions.SaveDictionaryVersion(Episode episode, String dictionary, String section, Int32 version)

Solution

  • After a lot of trial and error I discovered that an entity only indirectly connected to the erroring entity was still hanging around on the context, and keeping an entity with id 0 around. I had been clearing each EntitySet that contained non-lookup data - it turns out that this is not sufficient. Investigating within VS wasn't providing me an easy way to actually find the entity in question, however a profiling with ANTS revealed a few too many things laying around connected solely to my 'lookup' EntitySet entities.

    My 'fix' for this is to now clear all of my EntitySets as below:

    foreach (var set in _context.EntityContainer.EntitySets)
    {
        set.Clear();
    }
    

    What still baffles me is that this was an intermittent error; sometimes it didn't matter that multiple entities of type T with Id 0 were on the context, and other times it would error.