DATABASE

SQL Server 2012 : Distributed Transactions (part 4) - Using a Resource Manager in a Successful Transaction

1/10/2014 2:57:39 AM

5. Using a Resource Manager in a Successful Transaction

Using the RM in transactional code is really simple. You just wrap it in a TransactionScope, as shown here:

var vrm = new VolatileRM("RM1");
Console.WriteLine("Member Value:" + vrm.MemberValue);

using (var tsc = new TransactionScope())
{
vrm.MemberValue = 3;
tsc.Complete();
}
Console.WriteLine("Member Value:" + vrm.MemberValue);

When you run this code, you should see the following output indicating that the resource manager participated in a successful transaction:

Member Value: 0
RM1: MemberValue setter – EnlistVolatile
RM1: Prepare
RM1: Commit
Member Value: 3

As you can see, the RM enlists in the prepare and commit phases of the two-phase commit process.

Using the Resource Manager When the Caller Issues a Rollback

Now you’ll modify the code. Comment out the tsc.Complete() statement and run the application again. You should see the following output, indicating that the resource manager participated in a transaction that was rolled back:

Member Value: 0
RM1: MemberValue setter - EnlistVolatile
RM1: Rollback
Member Value: 0

By commenting out the tsc.Complete() statement, you are simulating a condition in which the application that uses the RMs enforces a rollback.

Tip

It’s best practice to always place the tsc.Complete() statement as the very last line of code within your TransactionScope blocks. Doing so ensures that it won’t get executed if an exception occurs anywhere within the block.

Instead of managing the prepare and commit phases, the code instead reacts to the rollback phase, and the final value of the member variable is unchanged from the original value.

Using the Resource Manager When It Issues a Rollback

Now go ahead and put tsc.Complete back in the code and modify the Prepare method of the RM. Comment out the Prepared method call and put in a ForceRollBack call instead, as follows:

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

The RM now issues a rollback. When you execute the application with tsc.Complete in place, a TransactionAbortedException exception is thrown because the resource manager itself issued a rollback.

Using the Resource Manager with Another Resource Manager

Now you’ll restore the Prepare method of the RM back to its original state so that a rollback isn’t issued. Back in the host application, modify the original code to include a second RM participating in the same transaction, as shown here:

var vrm = new VolatileRM("RM1");
var vrm2 = new VolatileRM("RM2");
Console.WriteLine("Member Value 1:" + vrm.MemberValue);
Console.WriteLine("Member Value 2:" + vrm2.MemberValue);

using (var tsc = new TransactionScope())
{
...
vrm.MemberValue = 3;
vrm2.MemberValue = 5;
tsc.Complete();
}

Console.WriteLine("Member Value 1:" + vrm.MemberValue);
Console.WriteLine("Member Value 2:" + vrm2.MemberValue);

As you can see, the code simply enlists another instance of the RM being used in the same transaction. When this code is executed, the following output indicates that two instances of the resource manager worked independently within a single transaction:

Member Value: 0
Member Value: 0
RM1: MemberValue setter - EnlistVolatile
RM2: MemberValue setter - EnlistVolatile
RM1: Prepare
RM2: Prepare
RM1: Commit
RM2: Commit
Member Value: 3
Member Value: 5

As you can see, when multiple RMs are involved in the transaction, the appropriate prepare, commit, or rollback phases are called for each RM in succession. As an exercise, you could modify the RM code to include a ForceRollBack and see the succession of events if one of the RMs issues a rollback to the entire transaction.

We’ve saved the best part for last. Remember that SqlConnection is also an RM, so you can retry this experiment with an instance of SqlConnection, a SqlCommand, and a database query executed within the same transaction that VolatileRM is enlisted in. To do so, modify the code to match this:

var vrm = new VolatileRM("RM1");
Console.WriteLine("Member Value:" + vrm.MemberValue);

const string connStr =
"Data Source=(local);Initial Catalog=Test1;Integrated Security=SSPI;";

const string cmdText = "UPDATE FromTable SET Amount = Amount - 50";

using (var tsc = new TransactionScope())
{
vrm.MemberValue = 3;

using (SqlConnection conn1 = new SqlConnection(connStr))
{
SqlCommand cmd1 = conn1.CreateCommand();
cmd1.CommandText = cmdText;
conn1.Open();
cmd1.ExecuteNonQuery();
}
tsc.Complete();
}

Console.WriteLine("Member Value:" + vrm.MemberValue);

By doing so, you would note that your VolatileRM now participates in the same transaction that a database query has enlisted itself in. This is something that BEGIN DISTRIBUTED TRANSACTION cannot do because by its very nature it talks to database queries, which cannot perform nondatabase operations. Unless, that is, you are using SQL CLR, which is where things can get a bit blurry.

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
  •  
    Top 10
    Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
    Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
    3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
    3 Tips for Maintaining Your Cell Phone Battery (part 1) - Charge Smart
    OPEL MERIVA : Making a grand entrance
    FORD MONDEO 2.0 ECOBOOST : Modern Mondeo
    BMW 650i COUPE : Sexy retooling of BMW's 6-series
    BMW 120d; M135i - Finely tuned
    PHP Tutorials : Storing Images in MySQL with PHP (part 2) - Creating the HTML, Inserting the Image into MySQL
    PHP Tutorials : Storing Images in MySQL with PHP (part 1) - Why store binary files in MySQL using PHP?
    REVIEW
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    VIDEO TUTORIAL
    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
    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