The purpose of a transaction is to group a bunch of actions that an application takes together, and to either perform all of them or none of them as a unit. It’s a pretty reasonable assumption, therefore, that a transaction should be sure that it includes all the actions an application intended before committing. We certainly don’t want a partial transaction to commit. Furthermore, in a distributed application, we don’t want any zombie transaction segments to hang around.
The simple case is, well, simple. If I have a transaction that consists of a straight line of operations from a single thread of an application, the fact that the application said “commit” is probably enough.
In other, slightly more complex cases, the application is embedded in an enterprise framework, such as COM+. That framework will have rules that govern when an application segment that it is controlling is considered complete. For instance, this is what is behind COM+’s DisableCommit, or Indigo’s AutoCompleteTransaction property.
Behind the scenes, logically what is happening in these systems is that the framework is enlisting in the transaction. The resource the enlistment is governing is that application segment’s notion of completeness. If the segment is complete, based on the framework’s rules for completeness, the enlistment will vote yes, otherwise it will veto. Furthermore, the frameworks will also be careful to ensure that no failures during communication are reported back as errors, and not hidden.
Here is a case where the enterprise framework is doing quite a bit of work for the application in order to ensure correctness. But, System.Transactions decomposes transactions out of the enterprise framework, so what should an application do when it’s just using System.Transactions?
There are two underlying tools available. The first is TransactionScope. This is a thread local mechanism to ensure that the caller states specifically that it is done with the transaction. If that is used throughout the application, then many of the completeness issues become moot.
The second mechanism is DependentTransaction. This is a form of Transaction that is created using the DependentClone method of an existing Transaction object. A DependentTransaction is both a normal Transaction object – you can enlist on it, you can issue Rollback, you can get the Identifier – and it incorporates a completion safety feature. The application must call Complete on this object when it is done using it. This is used internally by Indigo and by TransactionScope to ensure their completion safety. However, it can also be used directly by an application.
There are two forms of DependentTransaction, which I’ll go into in my next post.
Update: A comment pointed out that I probably meant SetComplete, rather than DisableCommit. SetComplete is certainly applicable, and at first I just agreed. However, I think both are applicable. The goal for the transaction system is to have the application segments assert that they are ok with transaction commitment proceeding -- effectively from any instruction following the call used to make that assertion. DisableCommit/EnableCommit/SetComplete all play with that assertion in varying ways.
Posted
Mar 28 2005, 06:09 AM
by
jim-johnson