DATABASE

SQL Server 2012 : Distributed Transactions (part 3) - Distributed Transactions in the .NET Framework - Writing Your Own Resource Manager

1/10/2014 2:56:59 AM

4.1 Writing Your Own Resource Manager

It is only reasonable to expect that because databases are the most critical part of the architecture (at least to database developers and administrators!), they have had fantastic transactional support for a long time. But don’t you want your other, nondatabase operations to be transactional as well if they also could benefit from transactional behavior?

Let’s consider the simple operation of setting a value to an integer and wrapping that as a part of a transaction, as shown in the following code snippet. The first question is: How do you set a value for an integer?

int myInt;
myInt = 10;

Unfortunately, wrapping this code in a TransactionScope won’t make it transactional. This is because System.Int32 is not smart enough to understand that it is being wrapped inside a TransactionScope and that it should auto-enlist within a running transaction. This is probably a good thing, because in the event of a rollback, to perform a graceful recovery, System.Int32 would have to maintain a previous version. You probably wouldn’t want to pay this overhead for all your integers. So you need to write a class that lets you maintain enough history in the event of a rollback. This class should also be able to interact with a TM and listen for various two-phase commit notifications. To do so, this class, or the RM you are writing, must implement the IEnlistmentNotification interface. This interface requires you to implement certain methods that are called at the appropriate points in time by the TC during the two phases of a two-phase commit process.

Here are the methods that IEnlistmentNotification requires you to implement:

  • Commit Notifies the RM that the transaction has been committed. The RM then makes the changes permanent.

  • Rollback Notifies the RM that the transaction has been rolled back. The RM then reverts to the previous stable state.

  • Prepare Called during the first (prepare) phase of a distributed transaction—when the TM asks the participants whether they are ready to commit. If the TM receives a successful notification from each participating RM, it calls the Commit methods.

  • InDoubt Notifies the RMs if the TM loses contact with one or more participants in the transaction. In this situation, the status of the transaction is unknown, and the application logic must decide whether to revert to the previous consistent state or remain in an inconsistent state.

Example 3 puts all of these concepts into actual code. It shows a full implementation of a volatile RM.

Example 3. Implementing your own resource manager.

public class VolatileRM : IEnlistmentNotification
{
private string _whoAmI = "";
public VolatileRM(string whoAmI)
{
this._whoAmI = whoAmI;
}

private int _memberValue = 0;
private int _oldMemberValue = 0;
public int MemberValue
{
get
{
return this._memberValue;
}

set
{
Transaction tran = Transaction.Current;
if (tran != null)
{
Console.WriteLine(
this._whoAmI + ": MemberValue setter - EnlistVolatile");
tran.EnlistVolatile(this, EnlistmentOptions.None);
}
this._oldMemberValue = this._memberValue;
this._memberValue = value;
}
}

#region IEnlistmentNotification Members

public void Commit(Enlistment enlistment)
{
Console.WriteLine(this._whoAmI + ": Commit");

// Clear out _oldMemberValue
this._oldMemberValue = 0;
enlistment.Done();
}

public void InDoubt(Enlistment enlistment)
{
Console.WriteLine(this._whoAmI + ": InDoubt");
enlistment.Done();
}

public void Prepare(PreparingEnlistment preparingEnlistment)
{
Console.WriteLine(this._whoAmI + ": Prepare");
preparingEnlistment.Prepared();
}

public void Rollback(Enlistment enlistment)
{
Console.WriteLine(this._whoAmI + ": Rollback");

// Restore previous state
this._memberValue = this._oldMemberValue;
this._oldMemberValue = 0;
enlistment.Done();
}

#endregion
}

Let’s examine this code more closely. At the very top is a class that implements IEnlistmentNotification. This signifies that your RM will receive notifications from the current transaction manager:

public class VolatileRM : IEnlistmentNotification

The code begins with a private string variable named _whoAmI and a constructor. This will help you analyze the chain of events when more than one RM is involved.

private string _whoAmI = "";
public VolatileRM(string whoAmI)
{
this._whoAmI = whoAmI;
}

Next, the code defines two class-level variables named _memberValue and _oldMemberValue, followed by a MemberValue property. The motivation for writing this class is the fact that System.Int32 is unable to interact with an RM or maintain historical values to roll back integers. The MemberValue property’s get accessor exposes _memberValue, and its set accessor assigns a new value to _memberValue and then enlists in the currently running transaction. The _oldMemberValue variable holds the historical value that will be used in the event of a rollback.

private int _memberValue = 0;
private int _oldMemberValue = 0;
public int MemberValue
{
get { return _memberValue; }
set
{
Transaction tran = Transaction.Current;
if (tran != null)
{
Console.WriteLine(
tran._whoAmI + ": MemberValue setter - EnlistVolatile");
tran.EnlistVolatile(this, EnlistmentOptions.None);
}
this._oldMemberValue = this._memberValue;
this._memberValue = value;
}
}

As you can see, the code first attempts to find the current transaction in the Transaction.Current variable, and then uses the EnlistVolatile method to enlist in the current transaction in a volatile manner. Volatile enlistment is sufficient for this example. If you were working with a durable resource, you would call the EnlistDurable method instead. Last, the code performs the logic of assigning the new value and preserving the old value.

With the class and its data set up, the rest of the details involve hooking up implementation so that you can enlist in a current running transaction with the RM and perform the appropriate actions based on the notifications received. This functionality is implemented in the four methods that the IEnlistmentNotification interface requires you to implement. The TM calls the appropriate methods (Commit, Rollback, Prepare, and InDoubt) for you and passes in a System.Transactions.Enlistment variable as a parameter. After successfully performing each step, you should call the enlistment.Done() method to indicate that this step has done its work.

The only exception to this rule is the Prepare method, which receives a special kind of Enlistment, a System.Transactions.PreparingEnlistment variable, as a parameter, which inherits from the System.Transactions.Enlistment class. PreparingEnlistment adds a few methods to Enlistment:

  • ForceRollBack() or ForceRollBack(Exception) Notifies the TM that an error has occurred and that the current participating RM wants to issue a rollback. You can specify your own exception if you want.

  • Prepared Notifies the TM that this RM has successfully finished doing its part of the transaction (the prepare phase of the two-phase commit process).

  • byte[] RecoveryInformation Used to specify information to the TM in the event of reenlistment to perform a graceful recovery (in situations such as the RM crashing). Alternatively, you can call the base class method Done to act as an innocent bystander and observe the transaction but not really participate in it. If you call Done in the prepare phase, the TM skips notifying the RM of the second (commit) phase of a two-phase notification process.

Other  
  •  Protecting SQL Server Data : TRANSPARENT DATA ENCRYPTION (part 6) - Reversing the Implementation of TDE
  •  Protecting SQL Server Data : TRANSPARENT DATA ENCRYPTION (part 5) - Verifying TDE - Verification through Backup and Recovery
  •  Protecting SQL Server Data : TRANSPARENT DATA ENCRYPTION (part 4) - Verifying TDE - Using Dm_Database_Encryption_Keys
  •  Protecting SQL Server Data : TRANSPARENT DATA ENCRYPTION (part 3) - Implementing TDE - The User Database
  •  Protecting SQL Server Data : TRANSPARENT DATA ENCRYPTION (part 2) - Implementing TDE - Backup before Proceeding , The Master Database
  •  Protecting SQL Server Data : TRANSPARENT DATA ENCRYPTION (part 1) - How TDE Works, Considerations when Implementing TDE
  •  SQL Server 2012 : Isolation Levels (part 2) - Repeatable Read Isolation Level,Snapshot Isolation Level, Isolation Levels in ADO.NET
  •  SQL Server 2012 : Isolation Levels (part 1) - Read Uncommitted Isolation Level, Read Committed Isolation Level
  •  SQL Server 2012 : Local Transaction Support in SQL Server (part 2) - Implicit Transaction Mode, Batch-Scoped Transaction Mode
  •  SQL Server 2012 : Local Transaction Support in SQL Server (part 1) - Explicit Transaction Mode
  •  
    Most View
    Microsoft SharePoint 2010 Web Applications : Presentation Layer Overview - Ribbon (part 1)
    The Cyber-athletic Revolution – E-sports’ Era (Part 1)
    Windows Server 2003 : Implementing Software Restriction Policies (part 4) - Implementing Software Restriction Policies - Creating a Path Rule, Designating File Types
    Sql Server 2012 : Hierarchical Data and the Relational Database - Populating the Hierarchy (part 1)
    Two Is Better Than One - WD My Cloud Mirror
    Programming ASP.NET 3.5 : Data Source-Based Data Binding (part 3) - List Controls
    Windows 8 : Configuring networking (part 5) - Managing network settings - Understanding the dual TCP/IP stack in Windows 8, Configuring name resolution
    Nikon Coolpix A – An Appealing Camera For Sharp Images (Part 2)
    Canon PowerShot SX240 HS - A Powerful Perfection
    LG Intuition Review - Skirts The Line Between Smartphone And Tablet (Part 2)
    Popular Tags
    Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8 BlackBerry Android Ipad Iphone iOS
    Top 10
    Review : Acer Aspire R13
    Review : Microsoft Lumia 535
    Review : Olympus OM-D E-M5 Mark II
    TomTom Runner + MultiSport Cardio
    Timex Ironman Run Trainer 2.0
    Suunto Ambit3 Peak Sapphire HR
    Polar M400
    Garmin Forerunner 920XT
    Sharepoint 2013 : Content Model and Managed Metadata - Publishing, Un-publishing, and Republishing
    Sharepoint 2013 : Content Model and Managed Metadata - Content Type Hubs