NHibernate Cascade Behavior for Same Session Updates

Documentation on NHibernate cascade settings, discusses the settings in the context of calling the Save() Update() and Delete() methods. But I can find no discussion of cascade behavior in the context of the implicit update that occurs when one loads, modifies and saves entities on the same session. In this case an explicit call to update is not needed, so what happens regarding cascade settings?

This may seem a dumb question, but the reason I bring this up is that I am trying to figure out how NHibernate supports the concept of Aggregate Boundaries in the context of Domain Driven Design. Let me give an example that will illustrate what I am trying to get at.

Suppose I have the canonical invoice application with the entities Invoice, Buyer and LineItem. Invoice is an aggregate root and LineItem is in the same aggregate but Buyer is its own aggregate root.

I want to model this in NHibernate by configuring my mapping such that the cascade from Invoice to LineItem is All-DeleteOrphans and the one from Invoice to Buyer is None .

Based on the documentation I have read, using my desired cascade settings, if I am working with disconnected entities and I do the following, only the Invoice and LineItems will save:

disconnectedInvoice.ShippedDate = DateTime.Today();
disconnectedInvoice.LineItems[2].Backordered = true;
disconnectedInvoice.Buyer.Address = buyersNewAddress;

session.Update(disconnectedInvoice);
session.Flush();

What I don't see discussed anywhere is what happens when one retrieves the invoice, makes the same updates and flushes the session in a connected manner like so.

var invoice = session.Get<Invoice>(invoiceNumber);
invoice.ShippedDate = DateTime.Today();
invoice.LineItems[2].Backordered = true;
invoice.Buyer.Address = buyersNewAddress;
session.Flush();

The NHibernate documentation says that flush persists the changes for dirty entities associated with the session. Based on this one would presume that the updates to the Invoice, the Buyer and the LineItems will all be persisted.

However, this would seem to violate the concept behind the cascade rule. It would seem to me that for the purposes of deciding what entities to update upon flush, the session should look at those entities that were directly loaded (only the invoice in this case) and include indirectly loaded entities (the LineItems and the Buyer in this case) only if the cascade setting indicates they should be persisted.

I admit that this example represents bad DDD. If the Buyer isn't part of the aggregate then it should not be being updated at this time. Or at least it should not be being updated through the Invoice aggregate. However, DDD aside, the point I am actually more interested in is determining if cascade rules are honored for updates in the same-session scenario the same as they are in the disconnected scenario.


The NHibernate documentation says that flush persists the changes for dirty entities associated with the session.

The main issue is the difference between disconnected and connected entities. Cascading behaves the same for both, but it's the implicit updates that are different. For session loaded entities, there is no need to cascade the save to the Buyer since it'd be redundant. For a disconnected entity, you need the cascade since there will be no implicit updates to that Buyer because it was never explicitly merged into the session.

链接地址: http://www.djcxy.com/p/23242.html

上一篇: 在同一会话中删除并在Nhibernate中创建新的儿童收藏

下一篇: 用于相同会话更新的NHibernate级联行为