Masoud
Masoud

Reputation: 8181

Deleting an UnAttached entry from dbContext cause exception when using GraphDiff

I'm using GraphDiff library in my c# project to update a disconnected graph. My Document entity has a one-to-many relationship with DocumentRelationShip entity as ToDocumentRelationship navigation property. I want to delete DocumentRelationships myself if needed, so I call the UpdateGraph() method with false for third parameter. after calling UpdateGraph() method for a saved Document, the doc and its ToDocumentRelationship entries state are Detached. When I want to remove one of doc relations using following code:

using (var ctx = new MyDbContext())
{
   var doc = ctx.Documents
                .Include(x => x.ToDocumentRelationShips)
                .Where(x=>x.Id == 1234)
                .AsNoTracking().FirstOrDefault();
   ... 
   ctx.UpdateGraph(doc, opt => opt.OwnedCollection(x => x.ToDocumentRelationShips),
                   false);
   ...
   var docRelation = doc.ToDocumentRelationShips().First();
   if(someConditions)
   {           
       // at this point ctx.Entry(docRelation).State is Detached    
       ctx.Entry(docRelation).State = EntityState.Deleted; //<- Exception raise at this point
   }
   ctx.SaveChanges();
}

I get the error:

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

How can I solve this issue?

Upvotes: 0

Views: 48

Answers (1)

Steve Py
Steve Py

Reputation: 34793

I've had a quick look at this GraphDiff source and it looks like when it does this operation it is loading and tracking entities separately to the detached entities you give it when calling UpdateGraph. UpdateGraph returns a reference to the tracked entities. So what you will want to do to delete instances after the graph update is capture the tracked entities and make your modifications there. Since the document relationships are effectively children of the document, I would remove these through the document's navigation property collection rather than entity state:

var trackedDocument = ctx.UpdateGraph(doc, opt => opt.OwnedCollection(x => x.ToDocumentRelationShips),false);

...
var docRelation = trackedDocument.ToDocumentRelationShips().First();
if(someConditions)
{           
    trackedDocument.ToDocumentRelationships.Remove(docRelation);
}
ctx.SaveChanges();

That should resolve your issue. Attempting to use the .Entry(docRelation) from the detached copy would be attempting to attach it where the UpdateGraph has already loaded and tracked an instance, leading to the exception.

Upvotes: 1

Related Questions