So here's the scenario:
DDD states that you use a repository to get the aggregate root, then use that to add/remove to any collections it has.
Adding is simple, you simple call .Add(Item item)
on the Collection
you wish to add to. A new row is added to the database when you save. However, deleting is different - calling .Remove(Item item)
doesn't remove the item from the database, it simply removes the foreign key. So while, yes, it is technically no longer part of the collection anymore, it's still in the database.
Reading around, the only solution is to delete it using the data context. But according to DDD the domain object shouldn't be aware of the data context so therefore deleting will have to be done outside of the domain.
What is the right way to go about this? Or Is leaving the database full of orphans acceptable (perhaps running a routine to clear them out)?
In Connected Scenario, you can use the Remove or RemoveRange method to mark the record as Deleted . In Disconnected Scenario, you can attach it to the context and set its state as Deleted . Calling SaveChanges will send the delete query to the database.
Cascade delete in the database Many database systems also offer cascading behaviors that are triggered when an entity is deleted in the database. EF Core configures these behaviors based on the cascade delete behavior in the EF Core model when a database is created using EnsureCreated or EF Core migrations.
Cascade delete is enabled by default in Entity Framework for all types of relationships such as one-to-one, one-to-many and many-to-many.
I've solved this problem in the application I'm currently working on by using domain events; a DDD concept Eric Evans said should have been in his book.
While domain objects aren't allowed to know about the object context, an IDomainEventHandler
is - I've therefore got a DomainObjectDeletionHandler
which deletes 'removed' objects from the object context before control returns to my application layer and the changes are saved.
For more information, I've written a blog about my implementation of domain events and how I approached hooking everything together.
Hope that helps :)
Edit
For example, if you have an Order
class which has an OrderItems
collection of type OrderItem
:
public class Order
{
// Other stuff
public void RemoveOrderItem(int orderItemId)
{
var orderItemToRemove = OrderItems.First(oi => oi.Id == orderItemId)
OrderItems.Remove(orderItemToRemove);
DomainEvents.Raise(new OrderItemRemoved(orderItemToRemove));
}
}
When removing a child entity from a collection, EF will leave it as orphan, removing just the foreign key.
If you don't want to explicitly remove it using the DbContext, you can use what it is called "Identifying Relationship" (http://msdn.microsoft.com/en-us/library/ee373856.aspx at the bottom).
The trick is to set a composite primary key on the child including the parent's primary key.
Once you do that, when removing the entity from the parent's collection, it will be removed from the table as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With