When we started working on System.Transactions in .Net 2.0, we had a simple goal: to decompose transaction services down to a simple common set of interfaces; and in doing so to reduce the complexity associated with using transactions and extend their reach.
This gave us two basic goals to aim at: a very simple object model with few ties to any larger environment, and sufficiently high performance for simple transactions to remove the need for any custom environment.
The first goal led to a simple set of services that were available as a core feature of .Net 2.0. The application programmer typically only has to bracket the activities that are to be part of a transaction, so with .Net 2.0 their primary, and possibly sole, exposure to System.Transactions will be with TransactionScope. That class has a number of constructors that provide for various settings from timeout to COM+ styles of transaction inheritance. The typical pattern is likely to be (in C#):
using (TransactionScope ts = new TransactionScope ())
{
// the transaction is active within here
// ...
ts.Complete ();
}
There is no further exposure until the application needs to handle distribution. It does not require a special type of class, or custom attributes, or a specific run time. In fact, the expectation is that application environments, such as System.EnterpriseServices, will make use of it for their underlying transaction feature.
The second goal required that we achieve very high performance for transactions that had simple topologies and one resource. This was to avoid the pattern where components are built differently if the author expects that a single SQL connection will suffice. This is typically done for performance, and our goal was to remove the performance argument and reduce the design pattern choices to a common set.
Our approach was to build a transaction stack that, behind the scenes, staged a series of fallbacks to more and more capable transaction management engines. With this sort of structure, initial transaction creation is extremely cheap. Furthermore, there are features, known as promotable single phase enlistment, in System.Transactions that allow a database to assume control of a simple transaction topology, yet have that control revoked if the topology increases sufficiently. With this structure in place, our tests have shown very little difference between using System.Transactions and using ADO's single database transaction interfaces.
Between these two, we have a very simple object model, with a performance profile that means that you shouldn't have to code around it.
Posted
Feb 07 2005, 06:24 AM
by
jim-johnson