Thursday, November 10, 2011

NHibernate bi-directional - use it carefully (Part I)

A few days ago we've experienced a very strange behavior with NHibernate. Or so we thought... 
For the demonstration i will use a Customer that has many Orders. 

And so we did that:
customer.Orders.Remove(order);
CustomerRepository.SaveOrUpdate(customer);

The "strange" behavior was that the Customer itself has been deleted from the DB along with all of its other Orders.

the mappings were like this:

Customer.hbm.xml:
<set name="Orders" lazy="true" cascade="all-delete-orphan">
     <key column="CUSTOMER_ID" />
     <one-to-many class="Order" not-found="ignore" />
</set>


Order.hbm.xml:
<many-to-one name="Customer" class="Customer" column="CUSTOMER_ID" cascade="all-delete-orphan"/>


So, what went wrong? Why did NHibernate delete the customer when all we did was removing one order? the reason was:

When we removed one Order from the Customer.Orders list, NHibernate deleted this Order from the DB since we have cascade="all-delete-orphan" on Customer.Orders. 
But while deleting an Order, NHibernate also is deleting its Customer. Why? Because we have 
cascade="all-delete-orphan" on Order.Customer, meaning - we actually tell NHibernate to delete a Customer whenever one of its Orders is being deleted. And that's usually a stupid thing to do.



No comments:

Post a Comment