Nested Transactions
A nested transaction occurs when a new transaction is started on a session that is already inside the scope of an existing transaction. The new, nested transaction is said to be nested within (or below the level of) the existing transaction. Changes made within the nested transaction are invisible to the top-level transaction until the nested transaction is committed. Even then, the changes are not visible outside the top-level transaction until that transaction is committed. Providers that expose ITransactionLocal and support nested transactions can choose to support only a limited number of nested transactions, including zero.
For providers that support nested transactions, calling ITransactionLocal::StartTransaction on a session with an existing transaction begins a new transaction nested below the current transaction. The return level indicates the level of nesting: a return value of 1 indicates a top-level transaction (that is, a transaction that is not nested within another transaction); 2 indicates a second-level transaction (a transaction nested within a top-level transaction); and so on.
Each nested transaction is represented by a transaction object.
Calling ITransaction::Commit or ITransaction::Abort on the session object commits or aborts the transaction at the current (lowest) nesting level. Calling Commit or Abort on a transaction object nested at a given level commits or aborts the transaction at that nesting level. Committing or aborting a transaction commits or aborts all transactions nested below it as well.
Calling ITransaction::Commit or ITransaction::Abort on a transaction object with the fRetaining flag set to TRUE implicitly begins a new unit of work, and the transaction object remains valid. Calling Commit or Abort with fRetaining set to FALSE terminates the transaction, and the transaction object enters a zombie state. At this point, the only valid action that can be performed on the transaction object is to release it.
Before the resources used by a transaction object can be freed by the provider, the transaction object and all transaction objects nested below it must be released. Releasing a transaction object aborts any uncommitted work performed in that transaction.