Microsoft Transaction Server (MTS), COM+ 1.0, and the .NET CLR support the same automatic distributed transaction model. The .NET Framework provides support for transactional components through COM+ services. There are two key benefits to COM+ transactions:
They allow distributed transactions that span multiple data sources.
Objects that can participate in COM+ transactions are free from having to anticipate how they might be used within a transaction. A client can perform different tasks with multiple objects, all in the context of a single transaction without the participating objects being aware of the transaction.
Instances of a .NET Framework class can participate in automatic transactions. Once an object is marked to participate in a transaction, it automatically executes within a transaction. This transactional behavior is controlled by the value of the transaction attribute for the .NET class, ASP.NET page, or XML web service method using the object. This allows the instantiated object to be configured programmatically to participate automatically in an existing transaction, to start a new transaction, or to not participate in a transaction.
When a transactional object accesses a data resource, a transaction occurs according to the value of the declarative transaction attribute of the object. When the transactional object accesses a data resource, the data driver enlists in the transaction through the distributed transaction coordinator (DTC).
During the lifetime of an automatic transaction, the objects
participating in it can vote to either commit the transaction they
are participating in by calling the static SetComplete( )
method of the
ContextUtil
class or to abort the transaction by
calling the static SetAbort( )
method of the
ContextUtil
class. In the absence of an explicit
vote, the default is to commit the transaction. The transaction is
committed once it completes if none of the participating objects have
voted to abort.
Alternatively, you can apply the
AutoCompleteAttribute
attribute to a transactional
method. This attribute instructs .NET to automatically commit the
transaction, provided no exceptions are encountered. If an unhandled
exception is thrown, the transaction is automatically rolled back.
For a .NET Framework object to participate in an automatic transaction, it must be registered with COM+ component services. The following steps will prepare a class to participate in an automatic transaction:
Apply the TransactionAttribute
to the class, and
specify the transaction behavior, timeout, and isolation level.
Derive the class from ServicedComponent
allowing
access to COM+ services.
Sign the assembly with a strong name. Use the sn.exe utility to create a key pair with the following syntax:
sn -k MyApp.snk
Add the AssemblyKeyFileAttribute
or
AssemblyKeyNameAttribute
assembly attribute
specifying the file containing the key pair, for example:
[assembly: AssemblyKeyFileAttribute("MyApp.snk")]
Register the assembly containing the class with the COM+ catalog[2] by executing the .NET Services Registration Tool (regsvcs.exe) with the following syntax:
regsvcs /appname:MyApp MyAssembly.dll
This step isn’t strictly required. If a client calling the class is managed by the CLR, the registration is performed automatically.
This example is a simple .NET class that participates automatically in transactions:
using System.EnterpriseServices; using System.Runtime.CompilerServices; using System.Reflection; namespace ServicedComponentCS { [Transaction(TransactionOption.Required)] public class ServicedComponentTest : ServicedComponent { [AutoComplete] public void TranTest() { bool success = true; // ... do work and store the outcome to success variable if(success) { // don't need the next line since AutoComplete // ContextUtil.SetComplete(); } else { ContextUtil.SetAbort(); throw new System.Exception("Error in Serviced " + "Component. Transaction aborted."); } } } }
The TransactionOption.Required
attribute in this
example indicates that every method in this class must be used in a
transaction, but the method can use the existing transaction if one
has already been started in the caller’s context.
The full list of TransactionOption
values is
featured in Table 16-4.
[2] COM+ services are explored in detail in COM and .NET Component Services, by Juval Löwy (O’Reilly).