client transaction and the unit of work
If you look at the Miss Quackfaster example for the unit of work, be aware that, at the same time, behind the scenes, client transactions were created for each new form (by re-call). These client transactions are not created equal. The first client transaction - the one for the Boss
instance - becomes the root transaction from which another client transaction is spawned off as its "child-" or "sub-" transaction (sub-transaction). This root transaction is ultimately responsible for actually committing all the data to the database that has been accumulated during the unit of work (unless something goes wrong or Miss Quackfaster clicks Cancel instead of Save).
So walking the link/reference/relation from the boss to the car spawns off a sub-transaction, with the aforementioned root transaction as its parent. In contrast to the root transaction, the sub-transaction is not responsible for writing data to the database. If everything works out, data is passed to the parent transaction, in the hope that Miss Quackfaster will click Save in the Boss form, and the root transaction will write the modification to the database. On Miss Quackfaster's way from the car object to the fax object another sub-transaction is spawned off, this time with the aforementioned sub-transaction as its parent – making the root transaction the grand-parent, so to speak. This new transaction doesn't store anything in the database, either. Instead it passes its modification (the fax-number, remember?) to the previous generation – the sub-transaction for the car, that is. Here is a (simplified, not quite accurate) illustration of the process.
The red rectangles are client transactions, each of which is ultimately descendent from the root transaction, or root transaction itself (on the bottom of the picture). Just as sub-transactions are spawned upwards, data is copied downwards as soon as a child transaction commits its data – typically when the user clicks Save. The root transaction, ultimate ancestor of all sub-transactions, finally commits to the database – typically when the user clicks Save.
The fact that the domain object boxes are drawn inside the red client transaction-rectangles is not just artistic license. Remember that object data is loaded into and stored in transactions. A domain object is an empty shell with properties that don't contain values. Instead, properties know which (sub-) transaction actually holds these values and can retrieve them from there.
What's important here is
- transactions can spawn off sub-transactions, forming parent-transactions and child-transactions
- data is passed from child (i.e. sub-) transactions to parent transactions if and when the child transaction is told to
Commit()
its data - the client transaction with no parent - the root transaction - actually writes data to the database if and when the root transaction is told to
Commit()
its data
In a word: sub-transactions are spawned up the generations, data bubbles down the generations. When a user modifies and saves data in many objects stored in one or more sub-transactions, these modifications aggregate in the parent transaction. If the user cancels that parent transaction, these modifications from sub-transactions will be discarded. Not before the aggregated modifications on the bottom root transaction are committed, will all modifications be persisted.