Entity Framework Pitfalls: Deleting Orphans

The idea for this post came from Jimmy Bogard, of AutoMapper fame.

Entity Framework does not really have the notion of parents and children, only of relations. Some of these relations can be mandatory, others can be optional. It is possible to specify cascade delete rules, so that when an entity is removed from the database, all entities that depend on it are also removed. However, what happens if we remove a related (child) entity from it’s parent’s children collection? Consider this code:

   1: using (var ctx = new OrdersContext())
   2: {
   3:     var customer = ctx.Customers.First();
   4:     customer.Orders.Remove(customer.Orders.First());
   5:  
   6:     ctx.SaveChanges();
   7: }

What we are doing here is removing the association between an Order and its Customer. Because an Order cannot exist without a Customer, we are turning it into an orphan. It is basically the same as:

   1: var order = ctx.Orders.First();
   2: order.Customer = null;

Do note that we are not deleting anything, just removing the related (parent) reference. In this case, Entity Framework will, of course, fail, complaining about the missing required relation.

Entity Framework has really no workaround for this – at least, not that I know of – so you have to delete the child entities explicitly:

   1: var customer = ctx.Customers.First();
   2: var order = customer.Orders.First();
   3:  
   4: customer.Orders.Remove(order);
   5: ctx.Orders.Remove(order);
   6:  
   7: ctx.SaveChanges();

As a side note, NHibernate handles this very well, by setting the cascade option to delete-orphan.

                             

4 Comments

  • ObjectContext.DeleteObject() followed by SaveChanges() will delete the order given no constraint violation exists on the database end as far as I know

  • But there is a constraint violation - a child needs a parent. And that is my solution!

  • Hi Ricardo,

    Correct me if I'm wrong but I think that is a 1 to many relation.

    One order only belongs to one customer but one customer can place many orders.

    Being that the case, deleting the order shouldn't delete the customer anyway.

    I think all you said is valid, but if you used the Order Header / Order Lines collection in the example would be more correct.

    Great blog by the way!
    :)

  • Hi, Ricardo!

    Sure, it's a many to one. The point is: when you remove a child of its containing collection, unlike NHibernate, EF will fail. The workaround in EF is to explicitly remove the child, whereas in NH it automatically detects this and does it implicitly.

    Thanks, keep coming by! ;-)

Add a Comment

As it will appear on the website

Not displayed

Your website