Table of contents
No headers

In absence of any other settings, performing an operation, such as a save or delete, on a single object will only affect that single object.  Often, though, you have related objects that you want to perform similar actions on--or, equivalently, a single "object" may have other objects, and collections of objects, to represent its properties.  To express this type of relationship, you can set Cascade properties on relations to and from the object.

The two basic types of cascades are "Edit/Update" and "Delete".  An "Edit/Update" cascade merely denotes a basic relationship where both ends of the relation are considered, conceptually, part of the same object.  As a simple example, you might have an Order and that Order has many OrderLine objects in a many-to-one relationship.  When we save the order, we want the associated OrderLines to be saved automatically.  If the relation has the "Edit/Update" Cascade set, then saving the Order (e.g. by calling "scope.Repository.Save(order)") will also save the order's associated OrderLine objects without any additional database calls being required.

A "Delete" cascade will require that related records be removed from the database when the base object is deleted.  So, when we remove an OrderLine from the list of OrderLines on the Order. we want that OrderLine to be deleted from the database.  To do that, we would require a "Delete" Cascade property.

A relation can have either type of cascade set, but commonly we would require both types, which is denoted by "All".  "All" has two subtypes, which differ in how they deal with child records being removed from their parents.  Normally you would use the  "All (delete on removal from collection)" setting for owned collections.  When the item is removed from the collection, it is deleted by the database.

Both sides of relationships allow the setting of cascade properties.  For example, let's say the Order has an associated AdPicture class that stores a blob image that the client has provided.  When we save the Order, we want to have the save cascade to AdPicture.  When we delete the Order, we also want to delete the AdPicture.  To do both of these things, we would set the cascade on the relationship to "All".  Normally you will want cascades to flow from a single object to its many related objects, but sometimes a one-to-many relationship actually corresponds more closely to a one-to-one, and so relationships should go both ways.

When setting up the cascades for your model, you should decide which objects are "owner" objects.  In other words, these objects live independent of other objects.  Each of these owner objects should cascade to its "slave" objects.  For example, the Order would be an owner, and the OrderLine would be a slave.  You should set up appropriate cascades from owner to slave objects so that you only need to save / delete the owner object and the slave objects take care of themselves.  Another example of an owner object would be an item in a lookup table.  That object lives independently of other objects, so it wouldn't normally have a cascade pointing into it, though if it has associated details, it might have a cascade pointing to those details.

Regarding many-to-one relationships, there is a special case that comes up once in a while.  Sometimes you want to change the owner of an object.  In our previous example, we might want to move an OrderLine to a different order.  If you need to do this, you must select "All (no action on removal from collection)".  It will also now be up to you to manage the lifecycle of the OrderLine object.  NHibernate will no longer automatically delete it when you remove it from the collection, but will only delete it when you explicitly do so, or as part of a regular cascade from its owner object.

Tag page
You must login to post a comment.