What is the right way to delete all of the collection items of an EF entity? In the code below, DocumentItems is the collection of related document items for a document. Thi
Yeah, a year old, but on a minor note... since DeleteObject takes one parameter, which is the same type as the argument for the lambda expression, you can just use:
entityCollection.ToList().ForEach(ctx.DeleteObject);
I am not sure if VB supports a similar syntax, though. Anyone?
Clear just removes the reference but doesn't delete the entity.
In your situation
existing.DocumentItems.Clear();
All DocumentItems
in the EntitySet
will get cleared but you will have to Remove/Delete the actual DocumentItem
or the commit with fail, just the same as it would if you tried to delete it in the database.
You need to loop through detach any references, and then delete the entity you wish to remove (unless its nullable
and in your situation, it is not)
Alternatively, I have seen implementations that use clear, and an AssociationChangedHandler
to automatically delete the old object. Basically, if the change is a "delete/remove" it calls DeleteObject()
on the orphaned object.
This is one way of deleting the items in the collection.
VB
TEntityCollection.ToList().ForEach(Sub(o) ctx.DeleteObject(o))
C#
TEntityCollection.ToList().ForEach(x => ctx.DeleteObject(x))
Then you need to call
ctx.SaveChanges()
Just to answer to Nix comment to the answer,
it seems to me that the EntityCollection.Remove()
method only marks for deletion the relationships and not the entities, just as the EntityCollection.Clear()
method does.
I know that documentation says that also the entity will be marked for deletion but in my test I've got the behavior I described (anyone can explain me why?).
So, if you have a one to many foreign key constraint in your conceptual model, you cannot save the changes to the context in the persistence store.
The only way I found (since I don't want to CascadeDelete
) is looping through the children and invoke context.DeleteObject
on each of them, thus removing the entity and the associated relationship.
Trick: When setting up the relationship between Parent and Child, you'll HAVE TO create a "composite" key on the child. This way, when you tell the Parent to delete 1 or all of its children, the related records will actually be deleted from the database.
To configure composite key using Fluent API:
modelBuilder.Entity<Child>.HasKey(t => new { t.ParentId, t.ChildId });
Then, to delete the related children:
var parent = _context.Parents.SingleOrDefault(p => p.ParentId == parentId);
var childToRemove = parent.Children.First(); // Change the logic
parent.Children.Remove(childToRemove);
// or, you can delete all children
// parent.Children.Clear();
_context.SaveChanges();
Done!