Content by Category
.NET 1.x
.NET 2.0
.NET 3.0
.NET 3.5
.NET 4.0
.NET Assemblies
.NET Framework
.NET Getting Started
Accessibility
ADO.NET
Advertorials
Agile Development
AJAX
Architecture
ASP.NET
ASP.NET MVC
ASP.NET WebForms
Azure
B2B (Business Integration)
Bing
BizTalk
Book Excerpts
Build and Deploy
C#
C++
ClickOnce
Cloud Computing
Code Contracts
CODE on the Road!
COM+
Community
Conferences
Continuous Integration
Crystal Reports
CSLA.NET
CSS
Data
Design Patterns
Development Process
Display Technologies
Distributed Computing
DotNetNuke
DSL
Dynamic Programming
Editorials
Enterprise Services ("COM+")
Entity Framework
Events
Expression Blend
F#
Fox to Fox
Frameworks
Functional Programming
Git
Graphics
Internet Explorer 8.0
Interviews
iPhone
Iron Ruby
Java
Java Script
jQuery
LINQ
Linux
Mac OS X
MDX
Microsoft Application Blocks
Microsoft Business Rules Framework
Microsoft Dynamics
Microsoft Expression
Microsoft Office
Mobile Development
Mobile PC
Mono
MsBuild
Network
NHibernate
Object Oriented Development
Open Source
Opinion
Opinions
Oracle
ORM
Other Languages
Parallel Programming
Patterns
Podcasts
Post Mortem
PowerPoint
Print/Output
Product News
Product Reviews
Project Management
Python
Q&A
Rails
Rake
Reporting Services
REST
RIA Services
Ruby
Ruby on Rails
Search
Security
Services
SharePoint
Silverlight
SOA
Social Networks
Software & Law
Software Business
Source Control
Speech-Enabled Applications
SQL Server
SQL Server 2000
SQL Server 2005
SQL Server 2008
SQL Server CE/AnyWhere/Mobile/Compact
Subversion
Sync Framework
Tablet PC
TDD
Team System
Techniques
Testing and Quality Control
Tips
UI Design
UML
User Groups
VB Script
VB.NET
Version Control
VFP and .NET
VFP and SQL Server
Virtual Earth
Vista
Visual Basic
Visual Basic 6 (and older)
Visual FoxPro
Visual Studio .NET
Visual Studio 2005
Visual Studio 2008
Visual Studio 2010
Visual Studio Tools for Office
VSX
WCF
Web Development (general)
Web Services
WF
Whitepapers
Windows 7
Windows Azure
Windows Live
Windows Server
Windows Vista
WinForms
Workflow
WPF
XAML
XML
XNA
XSLT



DevConnections


 


DevLink

Reader rating:
Click here to read 9 comments about this article.
Article source: CoDe (2006 - May/Jun)


Article Pages:  1  2 3 - Next >


System.Transactions and ADO.NET 2.0

Data is the blood in your system; it sits in its comfortable home of a database, and camps out in the tent of XML, but it deserves to be worked with in a reliable and consistent manner. But why should only data-related operations be reliable? Shouldn’t you want to write reliable code for your other operations? The introduction of System.Transactions in .NET 2.0 brings a paradigm shift of how you will write reliable transactional code on the Windows platform. This article dives deep in the depths of how System.Transactions works, and how you can use it to your advantage. You will also see how you can leverage existing System.Transactions integration within ADO.NET, and why you need to really understand what is under the magic carpet.

I have never met a programmer that intentionally wanted to write bad code. I have never met a client that was happy to receive an unreliable system. Face it-computer software that keeps an airplane in the sky, controls a CAT scan machine, and the software system that manages your and my payroll and retirement, needs to be reliable.

Reliability in computer software can be broken down into two main spheres: availability and predictability. Your software systems may be unavailable due to many reasons, one of which could be unpredictable software. But given the same set of inputs, why should you ever have an unpredictable set of outputs? You shouldn’t!! But because the inputs to a concurrent system depend on the concurrent load experienced by the server, the inputs on a highly available and concurrent system can vary over time, and thus it becomes necessary for you to wrap ATOMIC operations in CONSISTENT, ISOLATED, DURABLE operations. Such operations are also referred to as transactions.

A Little History of Transactions

I am not the first person to emphasize the importance of transactions, and I am pretty sure I will not be the last. Transactions have been our good programming friends since the days of the mainframe. Historically, databases typically have had fantastic transactional support. You can use the BEGIN TRANSACTION statement to wrap a number of statements within one single transactional block. You can also choose to use advanced features such as savepoints, nested transactions, and various isolation levels in your transactions. But again, why should only databases enjoy the luxury of being reliable?

Transactions could be necessary in other operations as well, and recognizing that fact, architectures have been built over time to support transactions on non-database operations. Generally such transactions are managed by Transaction Managers (TM), and resources that need to be managed in a transactional manner are managed by Resource Managers (RM).

A number of RMs work in cooperation with a TM to wrap a number of operations within a single transaction. A common example of an RM is the piece of code that abstracts a database connection, typically the SqlConnection class. A common example of a transaction manager on the Microsoft Windows platform is the MSDTC (Microsoft Distributed Transaction Coordinator).

Two-Phase Commit

By definition, a transaction managed by a Transaction Coordinator involves one or more than one resource that needs consistency in a highly concurrent environment. In general, you can tie a number of such operations together within a transaction using various mechanisms, the most common one of which is commonly referred to as a two-phase commit process. These steps show how a two-phase commit process works.

  1. An RM checks to see if a transaction is currently running, and if it is, it enlists itself within the running transaction.
  2. As a part of phase 1, also known as the prepare phase, the RM does its part and gives a green signal to the TM that it is ready to go.
  3. The TM keeps track of green signals from all enlisted RMs, and when the last RM in a transaction sends a green signal as success to the prepare phase, the TM requests the RMs to go ahead with phase 2.
  4. The RMs receive the green signal and go ahead and commit their work in the commit phase.
  5. If any RMs responded with a red signal at the end of the prepare phase, the TM asks everyone to roll back their work.

There is a lot of to and fro dialog going on between the RMs and the TM. Even though the amount of data isn’t much, it is indeed extremely chatty in nature. This can be a problem because on networks, chatty communication can seriously hurt performance due to network latencies. This is a serious disadvantage of MSDTC but is not the only downside of using MSDTC. Here are some additional downsides of using MSDTC.

  1. As mentioned, such network communication is rather chatty in nature, and leads to serious performance degradation due to network latencies.
  2. Such network communication can frequently be blocked by firewalls.
  3. Generally given the higher unpredictability (due to other RMs involved), such transactions frequently require RMs to lock their resources in a higher isolation level. For instance, a transaction being managed by MSDTC that involves a SqlConnection object will end up escalating the isolation level to Serializable, which is the oink oink version of a transaction. Serializable relies on exclusive locking thus blocking all other concurrent running transactions. This is, in fact, the perfect recipe for a deadlock because you are aggressively locking resources-without really knowing what you are locking. After all, the programming model for using such transactions, as you will see shortly, is rather simplistic.

But does every single transaction have to be distributed? Certainly not!! Therefore, every single transaction shouldn’t have to pay the heavy cost of a distributed transaction either.

In fact, when you wrap a transaction using the SqlTransaction object, your default isolation level is ReadCommitted, and SQL Server doesn’t consult the MSDTC whether it can commit or not. But when you run a transaction using the BEGIN DISTRIBUTED TRANSACTION command, SQL Server indeed does leverage MSDTC behind the scenes to run the transaction. Similarly, for non-database entities that do not need a heavy-duty TM such as the MSDTC, such entities can be managed by an alternate TM called the Lightweight Transaction Manager (LTM). It is important to realize, however, that what transaction manager you pick is transparent to you as a consumer of the RM. However, as an author of the RM, you will have to make that decision.

In other words, when you use the SqlConnection class, you don’t worry about which transaction manager you will use, you simply use the SqlConnection object. But if you were writing the implementation of SqlConnection-something Microsoft has already done for you-you would indeed sit back and think, “What TM do I need?”

&

By: Sahil Malik

Sahil Malik is a Microsoft MVP, INETA speaker, a .NET author, consultant, and trainer, and a well-rounded overweight geek. He has a passion for SharePoint, data access, and application architecture.

Sahil loves interacting with fellow geeks in real time. His talks are full of humor and practical nuggets. His talks tend to get very highly charged, fast moving, and highly interactive.

You should check out his blog at http://blah.winsmarts.com

sahilmalik@gmail.com

Fast Facts

The SqlConnection object exhibits PSPE only when connected to a SQL Server 2005 database. Previous versions enlist durably even with a single instance of SqlConnection. Also, SqlConnection connected to even a single instance of SQL Server 2005, from within SQLCLR (the CLR inside SQL Server) will always enlist in a durable manner.



Listing 1: A simple distributed transaction
using (TransactionScope txScope = 
    new TransactionScope())
{
   TransactionInformation info =
     Transaction.Current.TransactionInformation ;
   using (SqlConnection conn1 = 
      new SqlConnection(connStr1))
   {
      SqlCommand cmd1 = conn1.CreateCommand();
      cmd1.CommandText = 
        "Insert Into Test1(Test1) values ('xxx')";
      conn1.Open();
      cmd1.ExecuteNonQuery();
      conn1.Close();
   }

   using (SqlConnection conn2 = 
      new SqlConnection(connStr2))
   {
      SqlCommand cmd2 = conn2.CreateCommand();
      cmd2.CommandText = 
        "Insert Into Test2(Test2) values ('yyy')";
      Console.WriteLine(
         "Before:" + info.DistributedIdentifier);

      conn1.Open();
      Console.WriteLine(
         "After:" + info.DistributedIdentifier);
      cmd2.ExecuteNonQuery();
      conn2.Close();
   }
   txScope.Complete();
}


Article Pages:  1  2 3 - Next Page: 'What TM Do I Need?' >>

Page 1: System.Transactions and ADO.NET 2.0
Page 2: What TM Do I Need?
Page 3: Making TableAdapters Transactional

How would you rate the quality of this article?
1 2 3 4 5
Poor      Outstanding

Tell us why you rated the content this way. (optional)

Average rating:
2.2 out of 5

79 people have rated this article.

      Hacker Halted

 

DevLink