Click here to monitor SSC
  • Av rating:
  • Total votes: 240
  • Total comments: 28
Amirthalingam Prasanna

.NET 2.0 transaction model

22 June 2005

New transaction model addresses shortcomings

The Microsoft .NET 2.0 platform introduces a new namespace called System.Transactions that brings in a lightweight, simplified transaction model. This article discusses the shortcomings of current transaction models and introduces System.Transactions for .NET Framework 2.0 beta 2.

Currently there are two transaction models available in the .NET world, both of which are suited for certain situations. The first is part of the rich ADO.NET data providers. The second is the enterprise services transaction. Before we examine System.Transactions, let’s have a look at the current models.

The ADO.NET transaction model

The transaction handling model available as part of the .NET data providers is very simple. A general update statement might consist of the following steps:

C# Code

SqlConnection con = new SqlConnection("Connection String");
SqlTransaction tr = con.BeginTransaction();
SqlCommand cmd = new SqlCommand("Update Account set Balance=500 where AccountId=52", con, tr);
try
{
cmd.ExecuteNonQuery();
tr.Commit();
}
catch (Exception exc)
{
tr.Rollback();
}
finally
{
con.Close();
}

We created a transaction with the connection object and associated the transaction objects with the command objects. After executing the commands, we specified whether the transaction should commit or rollback. If there is an exception, we select a rollback, and if not, we are committing the transaction.

Though the ADO.NET transaction seems like a good model, there are a few problems associated with it. One of the biggest drawbacks occurs when you have updates for more than one database or resource grouped under a single transaction. As you can see in the previous code block, the transaction object is actually created from a connection to a single database. So there is no direct way of grouping updates to more than one database into a single transaction.

Also, when you manage transactions in an object-oriented scenario, database transactions are not ideal. In an object-oriented environment, many objects (such as customer, invoice number, etc.) coordinate together to complete a business process. If the business process is transactional, the transaction object might need to be passed around or there might be additional code involved to create a layer to manage the process.

Enterprise services transactions

Enterprise services transactions address most of the shortcomings of the ADO.NET transactions by providing a two-phase commit protocol and a distributed transaction manager. These two features enable you to have transactions independent of the database, and provide transactions in a declarative manner.

The following code shows a simple AccountManager class that accepts two accounts and performs a transfer between the two. The transfer is completed by depositing cash into one account and withdrawing cash from the other, with each method separately updating the balances of the accounts in the database. If any of these methods generates an error, the entire transfer method will be rolled back.

C# Code

[Transaction(TransactionOption.Required)]
class AccountManager : ServicedComponent
{
[AutoComplete()]
void TransferCash(Account from, Account to, double amt)
{
from.Withdraw(amt);
to.Deposit(amt);
}
}

If you look at the above code block, we are not explicitly creating any transaction objects. We are using declarative transactions to mark areas where transactions will be used. The Autocomplete attribute specifies that the transaction should be commited if no errors are generated. The Transaction attribute paired with TransactionOption.Required specifies that the objects we create from AccountManager will be transactional and will always run under a transaction.

With this model, you can access more than one resource and enlist them in one transaction. In the above code, for example, the withdrawal method can update one database and the deposit method can update another database.

But there are still a few problems in this model. First, your class needs to inherit from the ServicedComponent class to take advantage of enterprise service transactions. With the single inheritance model, most .NET languages will restrict your class from inheriting from any other base class.

Another drawback is that enterprise service transactions are always taken as a distributed transaction. Even if you are using a single database, enterprise services will still take it as a distributed transaction and handle it as such. As a result, you might end up using more resources than needed.

Another problem is that the components you create need to be deployed in component services to run under the COM+ context. Though .NET simplifies this deployment a great deal, you still need to place a strong name for the assembly with serviced components and make sure the settings for the components are set properly.

Introducing System.Transactions

The System.Transactions model is a new addition to the .NET 2.0 framework. It addresses the shortcomings in the above discussed models, and brings the best features of the ADO.NET and enterprise services transaction models together.

In System.Transactions, you have the TransactionScope object you can use to scope a set of statements and group them under one transaction. The following System.Transactions model generates the same transaction we saw in the enterprise services example.

C# Code

class AccountManager
{
void TransferCash(Account from, Account to, double amt)
{
using(TransactionScope scope=new TransactionScope())
{
from.Withdraw(amt);
to.Deposit(amt);
scope.Complete();
}
}
}

If you look at the above code, our class is not inheriting any base classes to enable transactions. All we are doing is using a TransactionScope object and wrapping the method calls accessing the database with a using block. Once complete, we are setting the scope to complete and indicating the transaction should commit now. But what if the withdrawal method creates an exception? Then the complete method for the scope will not be called and the transaction will be rolled back.

System.Transactions has the unique capability of knowing whether to use a distributed transaction or not. It will use a lightweight transaction if there is a single domain accessing a single database, or it will use a distributed transaction similar to the enterprise services transaction model if there are multiple databases to access.

In most scenarios, you will interact with the TransactionScope object for your transaction handling work. You can even nest transaction scopes and provide transaction options to specify how each of the blocks interact with each other. Below we have a method to log successful withdrawals and we need to make sure this method will attach itself to a root transaction if it exists or spawn a new transaction otherwise:

C# Code

void LogWithdrawals(Account account,double amt)
{
using (TransactionScope scope = new TransactionScope (TransactionScopeOption.Required))
{
//database calls to log details
}

}

In the above code, we have created a transaction scope option with the value Required. This is used to specify that the block of code should always be within a transaction. If there is an existing transaction, the scope within LogWithdrawals will join with the root transaction; otherwise it will create a new one. The other transaction scope options available are RequiresNew (will always create a new transaction) and Suppress (will never be part of a transaction). These options can be used to change the way nested transactions will participate in the overall transaction.

You can also adorn a transaction scope with a TransactionOption object to specify the isolation level and the timeout period of the transaction. For example:

C# Code

TransactionOptions options = new TransactionOptions();
options.IsolationLevel = IsolationLevel.ReadCommitted;
options.Timeout = new TimeSpan(0, 1, 0);
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew,options))
{
//code within transaction
}

The above code sets our transaction scope to use an isolation level of read committed; we have also set a timeout of one minute for our transaction.

Conclusion

System.Transactions is a welcome transaction model for .NET 2.0 beta 2 that addresses shortcomings of current .NET transaction models.

Amirthalingam Prasanna

Author profile:

Prasanna is a software engineer, technical author and trainer with many years of development and consulting experience in the software development industry. He is a Microsoft MVP in the Visual developer category, and a MCPD on enterprise application development. He has authored many articles and has worked on content creation for many Microsoft certification exams and courses. He is also a frequent speaker at Microsoft technology conferences and events. You can read his blog at www.prasanna.ws and e-mail him at feedback@prasanna.ws

Search for other articles by Amirthalingam Prasanna

Rate this article:   Avg rating: from a total of 240 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: nice article
Posted by: Anonymous (not signed in)
Posted on: Thursday, September 07, 2006 at 3:08 PM
Message: nice article Prasanna

- Satish

Subject: Simple and Articulate
Posted by: Anonymous (not signed in)
Posted on: Tuesday, September 19, 2006 at 9:53 PM
Message: Wish we have a lot more articles like these. Communicated in a simple and effective manner - Way to go!

- Krishna
krish81_kkr@yahoo.com

Subject: Good Article
Posted by: Anonymous (not signed in)
Posted on: Monday, September 25, 2006 at 3:30 AM
Message: Hoping for new and bright articles like these to come in the future.

Subject: IT IS A GREAT ARTICLE!
Posted by: Anonymous (not signed in)
Posted on: Monday, September 25, 2006 at 10:36 PM
Message: Buddy Parsana you’re a smart cookie.I used this article to get some ideas on how to create my Business Intermediate Layer. Keep the good work up.

--Fernando Rohan

Subject: Good article
Posted by: Anonymous (not signed in)
Posted on: Thursday, October 12, 2006 at 11:51 AM
Message: I like the article, but I just have quick question. You mention that enterprise service transaction are always taken as a distributed transaciton. What do you mean by that?

Subject: Cool one
Posted by: Anonymous (not signed in)
Posted on: Tuesday, November 07, 2006 at 6:03 AM
Message: Very nice article. Also check out the emulation of this model on net 1.1 at codeproject:
http://www.codeproject.com/cs/database/transactionScope_in_1_1.asp

Subject: Nice article
Posted by: Anonymous (not signed in)
Posted on: Friday, November 17, 2006 at 1:37 PM
Message: Good one
- Prasad MCSD.NET, MCPD

Subject: good
Posted by: Anonymous (not signed in)
Posted on: Thursday, December 14, 2006 at 12:09 AM
Message: nice article

Subject: good
Posted by: Anonymous (not signed in)
Posted on: Tuesday, January 30, 2007 at 5:22 AM
Message: this is very good article
thanks prasanna

can u give some more code which can explain different different bank transactions


Subject: Very Good
Posted by: Anonymous (not signed in)
Posted on: Monday, February 26, 2007 at 2:59 AM
Message: Its a very Good Article, more helpfull is you provide few more scenarios

Subject: Nice
Posted by: Anonymous (not signed in)
Posted on: Tuesday, March 27, 2007 at 12:55 AM
Message: very good article.

Subject: This only works well on SQL 2005
Posted by: Anonymous (not signed in)
Posted on: Wednesday, March 28, 2007 at 2:52 AM
Message: If you try this (System.Transactions) in SQL2000 all your transactions are promoted to distributed transactions. Very anoying as this is so much better than 1.1

Subject: Superb
Posted by: Anonymous (not signed in)
Posted on: Wednesday, May 09, 2007 at 12:05 AM
Message: Nicely Put and simple to understand. Just Great

Subject: GREAT
Posted by: Senthil Kumar @ Klsen (not signed in)
Posted on: Friday, July 13, 2007 at 6:12 AM
Message: It is nice , I understand the coding , It is very useful one my real time coding. Thanks much !!!!

Subject: good
Posted by: Anonymous (not signed in)
Posted on: Wednesday, July 25, 2007 at 7:54 AM
Message: Give me the Difference in above transaction types.
Also give me the details abt at how much level each
handles database changes.

Subject: better
Posted by: Anonymous (not signed in)
Posted on: Thursday, September 20, 2007 at 2:23 AM
Message: best

Subject: Problem
Posted by: Steve (view profile)
Posted on: Wednesday, October 03, 2007 at 7:54 PM
Message: This requires MSDTC to be running. You might want to add this to the article.

ie. does it work with sqlexpress 2005 ?

Subject: Great
Posted by: Anonymous (not signed in)
Posted on: Wednesday, October 17, 2007 at 8:47 AM
Message: hi, this article is very nice . give some example about nesting transaction scope

Subject: Very Good
Posted by: Boney.M, (not signed in)
Posted on: Thursday, October 18, 2007 at 3:16 AM
Message: Wish we have a lot more articles like these

Subject: Help on global transaction handling
Posted by: vijaykumar (view profile)
Posted on: Monday, October 29, 2007 at 7:08 AM
Message: Nice article,

Respected Amirthalingam Prasanna sir

i need help on how to implement global transaction management in vb.net, as i use right now a single transaction management, but through my form first of all iam locking the seats of tour then minus the inventory, and after booking confirmation iam entering data in booking table so i have used two various buttons for this work, so i wish to use global transaction management in my form, please kindly help me on doing this work.

Thanks and Regards,
Vijaykumar

Subject: system.transaction with remote machine
Posted by: Anonymous (not signed in)
Posted on: Tuesday, November 27, 2007 at 8:10 AM
Message: very nice article. worked perfectly in local host using system.transaction example class AccountManager{void TransferCash(Account from, Account to, double amt){using(TransactionScope scope=new TransactionScope()){from.Withdraw(amt);to.Deposit(amt);scope.Complete();}}}

but throwing some exeptions when the DB server is a remote machine (web server machine and db on are separate). any ideas on how to fix that?

Subject: userful article
Posted by: Jayant Sande (not signed in)
Posted on: Tuesday, December 18, 2007 at 10:18 PM
Message: helped me solve a scenario where database and non database process involve in a transaction.
I observed that transactionscope is better than trivial begintransaction method.

let me any resource saying more about internals of transctionscope.

thanks
Jayant

Subject: Great Article
Posted by: Pronobesh (not signed in)
Posted on: Friday, March 21, 2008 at 7:49 AM
Message: Article is really helpful....need to know more about transaction....thanks a lot

Subject: Nice intro to .NET 2.0 Transactions
Posted by: Nahom Tijnam (not signed in)
Posted on: Saturday, March 22, 2008 at 11:18 AM
Message: Hi Prasanna,

Your article provides a good starting point for .net 2.0 transactions. Its neat, simple and concise. Thanks.

Cheers,
Nahom

Subject: Helpful to understand Trasaction in dot net
Posted by: Anil Kumar Singh (not signed in)
Posted on: Wednesday, May 14, 2008 at 3:20 AM
Message: Hi Prasana.
Thank you for such type of useful article on transaction.

Thanks,
CK Anil

Subject: Simple and elegant article
Posted by: Prasad (view profile)
Posted on: Wednesday, May 28, 2008 at 3:38 PM
Message: Its enough to understand quickly what the System.Transaction is and how to use it.

Thank you.

Subject: What happens in Clustered envirnoment
Posted by: Lokesh SP (not signed in)
Posted on: Tuesday, June 24, 2008 at 8:14 AM
Message: It's a good article. And we would like to know more about how it works in a clustered environment.

Thanks and Regards
Lokesh.SP

Subject: Useful Sharing
Posted by: Ram (not signed in)
Posted on: Tuesday, July 22, 2008 at 6:25 PM
Message: This is very nice article. Great Job!. Keep it up.

 

Top Rated

Acceptance Testing with FitNesse: Multiplicities and Comparisons
 FitNesse is one of the most popular tools for unit testing since it is designed with a Wiki-style... Read more...

Acceptance Testing with FitNesse: Symbols, Variables and Code-behind Styles
 Although FitNesse can be used as a generic automated testing tool for both applications and databases,... Read more...

Acceptance Testing with FitNesse: Documentation and Infrastructure
 FitNesse is a popular general-purpose wiki-based framework for writing acceptance tests for software... Read more...

TortoiseSVN and Subversion Cookbook Part 11: Subversion and Oracle
 It is only recently that the tools have existed to make source-control easy for database developers.... Read more...

TortoiseSVN and Subversion Cookbook Part 10: Extending the reach of Subversion
 Subversion provides a good way of source-controlling a database, but many operations are best done from... Read more...

Most Viewed

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Calling Cross Domain Web Services in AJAX
 The latest craze for mashups involves making cross-domain calls to Web Services from APIs made publicly... Read more...

Web Parts in ASP.NET 2.0
 Most Web Parts implementations allow users to create a single portal page where they can personalize... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.