Removing entity from a Related Collection
I have seen this misunderstanding starting to popup more often on how to delete an entity from a related collection. Suppose we have the following entity data model where a Person has many Phones identified by 1-to-many association as shown.
Problem: You have an existing Phone entity that you want to remove from the customer’s Phone collection
So let’s see how someone just walking into EF does it and assumes that code should works.
In the above code, I am creating a new customer and phone entity, adding the new phone to the customer’s Phone collection followed by adding the entire customer object graph to the ObjectContext. When I call SaveChanges, EF inserts a new customer along with its related phone. Now to delete the phone, I am simply removing the phone from the Phone Collection of the customer and then call SaveChanges. When you do that you get the following exception.
Now you wonder why did you get a failed delete and what is this exception saying? Essentially when you remove the phone from the customer’s phone collection, you are simply detaching the relationship between the phone and the customer but actually not deleting the phone itself. So when you try to save the changes, EF says oh wait, I can’t delete this relationship because a phone must belong to a customer because the customerId property on the Phone is not nullable.
Now that i have explained you what the problem is, I kept on wondering why developers thought removing something from a collection meant deleting the entity itself? Actually the answers lies in the way how we initially added the phone to the customer’s phone collection. Notice in the above code, to create a new phone we simply add the phone to the customer's phone collection which basically not only attaches the phone to the customer’s phone collection but also inserts the phone. This leads the developers that they can apply the same concept to remove where removing a phone would actually mark it for deletion.
The correct way to remove the phone is to mark it for deletion. When you delete the phone, EF will automatically detach the phone from any of its relationship. Code below shows the correct code.
In the above code, after deleting the phone, I am displaying the total phones for the customer which is 0 because EF automatically removes the phone from the customer’s phone collection.
NOTE: There are edge cases where removing an entity from a collection also marks it for deletion like in the case of identifying relationship.