Enlisting Resources as Participants in a Transaction
Each resource participating in a transaction is managed by a resource manager, whose actions are coordinated by a transaction manager. The coordination is done through notifications given to subscribers who have enlisted in a transaction through the transaction manager.
This topic covers how a resource (or multiple resources) can be enlisted in a transaction, as well as the different types of enlistment. Thetopic covers how transaction commitment can be coordinated among enlisted resources.
Enlisting Resources in a Transaction
In order for a resource to participate in a transaction, it must enlist in the transaction. Theclass defines a set of methods whose names begin with Enlist that provide this functionality. The different Enlist methods correspond to the different types of enlistment that a resource manager may have. Specifically, you use the methods for volatile resources, and the method for durable resources. The durability (or conversely the volatility) of a resource manager refers to whether the resource manager supports failure recovery. If a resource manager supports failure recovery, it persists data to durable storage during Phase1 (prepare) such that if the resource manager goes down, it can re-enlist in the transaction upon recovery and perform the proper actions based on the notifications received from the TM. In general, volatile resource managers manage volatile resources such as an in-memory data structure (for example, an in-memory transacted-hashtable), and durable resource managers manage resources that have a more persistent backing store (for example, a database whose backing store is disk).
For simplicity, after deciding whether to use the EnlistDurable or EnlistVolatile method based on your resource's durability support, you should enlist your resource to participate in Two Phase Commit (2PC) by implementing theinterface for your resource manager. For more information on 2PC, see .
A single participant can enlist for more than one of these protocols by calling EnlistDurable and EnlistVolatile multiple times.
The EnlistDurable methods are used to enlist a resource manager for participation in the transaction as a durable resource. It is expected that if a durable resource manager is brought down in the middle of a transaction, it can perform recovery once it is brought back online by reenlisting (using themethod) in all transactions in which it was a participant and did not complete phase 2, and call once it finishes recovery processing. For more information on recovery, see .
The EnlistDurable methods all take aobject as their first parameter. The Guid is used by the transaction manager to associate a durable enlistment with a particular resource manager. As such, it is imperative that a resource manager consistently uses the same Guid to identify itself even across different resource managers upon restarting, otherwise the recovery can fail.
The second parameter of the EnlistDurable method is a reference to the object that the resource manager implements to receive transaction notifications. The overload you use informs the transaction manager whether your resource manager supports the Single Phase Commit (SPC) optimization. Most of the time you would implement the IEnlistmentNotification interface to take part in Two-Phase Commit (2PC). However, if you want to optimize the commit process, you can consider implementing theinterface for SPC. For more information on SPC, see and .
The third parameter is anenumeration, whose value can be either or . If the value is set to EnlistDuringPrepareRequired, the enlistment may enlist additional resource managers upon receiving the Prepare notification from the transaction manager. However, you should be aware that this type of enlistment is not eligible for the Single Phase Commit optimization.
Participants managing volatile resources such as a cache should enlist using the EnlistVolatile methods. Such objects might not be able to obtain the outcome of a transaction or recover the state of any transaction they participate in after a system failure.
As stated previously, a resource manager would make a volatile enlistment if it manages an in-memory, volatile resource. One of the benefits of using EnlistVolatile is that it does not force an unnecessary escalation of the transaction. For more information on transaction escalation, seetopic. Enlisting volatilely implies both a difference in how the enlistment is handled by the transaction manager, as well as what is expected of the resource manager by the transaction manager. This is because a volatile resource manager does not perform recovery. The EnlistVolatile methods do not take a Guid parameter, because a volatile resource manager does not perform recovery and would not call the Reenlist method which needs a Guid.
As with durable enlistments, whichever overload method you use to enlist denotes to the transaction manager whether your resource manager supports the Single Phase Commit optimization. Since a volatile resource manager cannot perform recovery, no recovery information is written for a volatile enlistment during the Prepare phase. Therefore, calling themethod results in an .
The following example shows how to enlist such an object as a participant in a transaction using the EnlistVolatile method.
Public Shared Sub Main() Try Using scope As TransactionScope = New TransactionScope() 'Create an enlistment object Dim myEnlistmentClass As New EnlistmentClass 'Enlist on the current transaction with the enlistment object Transaction.Current.EnlistVolatile(myEnlistmentClass, EnlistmentOptions.None) 'Perform transactional work here. 'Call complete on the TransactionScope based on console input Dim c As ConsoleKeyInfo While (True) Console.Write("Complete the transaction scope? [Y|N] ") c = Console.ReadKey() Console.WriteLine() If (c.KeyChar = "Y") Or (c.KeyChar = "y") Then scope.Complete() Exit While ElseIf ((c.KeyChar = "N") Or (c.KeyChar = "n")) Then Exit While End If End While End Using Catch ex As TransactionException Console.WriteLine(ex) Catch Console.WriteLine("Cannot complete transaction") Throw End Try End Sub End Class Public Class EnlistmentClass Implements IEnlistmentNotification Public Sub Prepare(ByVal myPreparingEnlistment As PreparingEnlistment) Implements System.Transactions.IEnlistmentNotification.Prepare Console.WriteLine("Prepare notification received") 'Perform transactional work 'If work finished correctly, reply with prepared myPreparingEnlistment.Prepared() End Sub Public Sub Commit(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.Commit Console.WriteLine("Commit notification received") 'Do any work necessary when commit notification is received 'Declare done on the enlistment myEnlistment.Done() End Sub Public Sub Rollback(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.Rollback Console.WriteLine("Rollback notification received") 'Do any work necessary when rollback notification is received 'Declare done on the enlistment myEnlistment.Done() End Sub Public Sub InDoubt(ByVal myEnlistment As Enlistment) Implements System.Transactions.IEnlistmentNotification.InDoubt Console.WriteLine("In doubt notification received") 'Do any work necessary when indout notification is received 'Declare done on the enlistment myEnlistment.Done() End Sub End Class
The Transaction class also provides themethod to enlist a Promotable Single Phase Enlistment (PSPE). This allows a durable resource manager (RM) to host and "own" a transaction that can later be escalated to be managed by the MSDTC if necessary. For more information on this, see .