.NET 2.0 transaction model

.NET 2.0 introduces a new System.Transactions namespace that brings in a lightweight, simplified transaction model.

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

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

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

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

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

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.

For more articles like this, sign up to the fortnightly Simple-Talk newsletter.

Tags: , , , , ,

  • 78097 views

  • Rate
    [Total: 240    Average: 3.9/5]
  • Anonymous

    nice article
    nice article Prasanna

    – Satish

  • Anonymous

    Simple and Articulate
    Wish we have a lot more articles like these. Communicated in a simple and effective manner – Way to go!

    – Krishna
    krish81_kkr@yahoo.com

  • Anonymous

    Good Article
    Hoping for new and bright articles like these to come in the future.

  • Anonymous

    IT IS A GREAT ARTICLE!
    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

  • Anonymous

    Good article
    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?

  • Anonymous

    Cool one
    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

  • Anonymous

    Nice article
    Good one
    – Prasad MCSD.NET, MCPD

  • Anonymous

    good
    nice article

  • Anonymous

    good
    this is very good article
    thanks prasanna

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

  • Anonymous

    Very Good
    Its a very Good Article, more helpfull is you provide few more scenarios

  • Anonymous

    Nice
    very good article.

  • Anonymous

    This only works well on SQL 2005
    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

  • Anonymous

    Superb
    Nicely Put and simple to understand. Just Great

  • Senthil Kumar @ Klsen

    GREAT
    It is nice , I understand the coding , It is very useful one my real time coding. Thanks much !!!!

  • Anonymous

    good
    Give me the Difference in above transaction types.
    Also give me the details abt at how much level each
    handles database changes.

  • Anonymous

    better
    best

  • Steve

    Problem
    This requires MSDTC to be running. You might want to add this to the article.

    ie. does it work with sqlexpress 2005 ?

  • Anonymous

    Great
    hi, this article is very nice . give some example about nesting transaction scope

  • Boney.M,

    Very Good
    Wish we have a lot more articles like these

  • vijaykumar

    Help on global transaction handling
    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

  • Anonymous

    system.transaction with remote machine
    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?

  • Jayant Sande

    userful article
    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

  • Pronobesh

    Great Article
    Article is really helpful….need to know more about transaction….thanks a lot

  • Nahom Tijnam

    Nice intro to .NET 2.0 Transactions
    Hi Prasanna,

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

    Cheers,
    Nahom

  • Anil Kumar Singh

    Helpful to understand Trasaction in dot net
    Hi Prasana.
    Thank you for such type of useful article on transaction.

    Thanks,
    CK Anil

  • Prasad

    Simple and elegant article
    Its enough to understand quickly what the System.Transaction is and how to use it.

    Thank you.

  • Lokesh SP

    What happens in Clustered envirnoment
    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

  • Ram

    Useful Sharing
    This is very nice article. Great Job!. Keep it up.