Go to DotNetFunda.com
  Welcome, Guest!  
LoginLogin  
{ Submit resources and get monthly gifts !!! }
Submit: Article | Interview Question | Joke | Question | Link || Search  
 Skip Navigation Links Home > Articles > Calling methods of different classes into same Transaction Scope using System.Transactions

All Articles | Post Articles

Calling methods of different classes into same Transaction Scope using System.Transactions

 Posted on: 5/4/2008 3:22:05 AM by SheoNarayan | Views: 810 | Category: ASP.NET | Level: Advance | Print Article
We must have came across a situation where we have to call methods of different classes under same transaction scope and rollback the operations if any error occurs during execution of any methods. For eg. If we have Debit and Credit class and DebitAmount method of Debit class executed successfully but an error occurred while calling CreditAmount method of Credit class, we should be able to rollback all operations done by DebitAmount method. In scenario like this we can use System.Transactions.TransactionScope to rollback all operations done by DebitAmount method.
Introduction

All most all of us generally use SqlTransaction in our day to day coding. But in this article I am going to explain about System.Transaction namespace that allows us to call different methods of different classes under a TransactionScope and commit the tranaction only if all of them are successfully executed.

Problem

SqlTransaction doesn't suits us in the scenaior explained above. As different methods of different classes are using their own SqlConnection object and we don't have any control over them.

For easy understanding of the above scenario, I am going to take example of Debit and Credit class that has DebitAmount and CreditAmount method with parameter as accountNo and amount. In my TransferAmount method, I have to call DebitAmount method of Debit class and then CreditAmount method of Credit class so that the transfer of fund happen successfully. So my normal code will look like:

Normal TransferAmount Method

- Hide Code

protected void TransferAmount(object sender, EventArgs e)
{
DebitBAL debit = new DebitBAL();
CreditBAL credit = new CreditBAL();

try
{
int dAccountNo = int.Parse(txtDAccountNo.Text);
int cAccountNo = int.Parse(txtCAccountNo.Text);
decimal amount = decimal.Parse(txtAmount.Text);

// Debit amount from the account
debit.DebitAmount(dAccountNo, amount);

// Credit amount to the account
credit.CreditAmount(cAccountNo, amount);

}
catch (Exception ee)
{
lblMessage.Text = ee.Message.ToString();
}
finally
{
debit.Dispose();
credit.Dispose();
}
}

In the above method, I am instantiating my Debit class (DebitBAL) and Credit class (CreditBAL) and calling DebitAmount and CreditAmount method respectively. The above code will work fine if no error will occur in the CreditAmount method. But the gotcha :) here is that if while calling CreditAmount method any error occurs then amount will be debited from the account but it will not be credited into other account. In this case we can't use SqlTransaction as we don't have any parameter to pass other than accountNo and amount and also both classes are using different SqlConnection objects to connect to the database.

Solution

In scenaio like this, System.Transaction namespace comes into the picture and this solves our problem very easily. This namespace has several classes but we are going to focus on TransactionScope class that makes the code block transactional. To overcome the problem identified above, we will need to modify our code as follows:

Modified code using System.Transactions.TransactionScope

- Hide Code

protected void TransferAmount(object sender, EventArgs e)
{
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))
{
DebitBAL debit = new DebitBAL();
CreditBAL credit = new CreditBAL();

try
{
int dAccountNo = int.Parse(txtDAccountNo.Text);
int cAccountNo = int.Parse(txtCAccountNo.Text);
decimal amount = decimal.Parse(txtAmount.Text);

// Debit amount from the account
debit.DebitAmount(dAccountNo, amount);

// Credit amount to the account
credit.CreditAmount(cAccountNo, amount);

// notify the TransactionScope that transaction is complete now
// If you will not write following statement the transaction
// will be automatially rolledback. There is no separate Rollback method for TransactionScope
ts.Complete();
}
catch (Exception ee)
{
lblMessage.Text = ee.Message.ToString();
}
finally
{
debit.Dispose();
credit.Dispose();
}

} // TransactionScope
}


In the above modified code, I am using TransactionScope class and instantiating with TransactionScopeOption.Required parameter and doing the same thing as I had done in my normal code (instantiating Debit and Credit class and calling respective methods). After my DebitAmount and CreditAmount method have been called I am calling Complete() method of the TransactionScrope class to notify it that all the operations within transaction scope completed successfully. You can notice that there is no separate method like rollback (rollback of of SqlTransaction) here so if you will not call ts.Complete() then automatically all operations will be rolled back as a result no change will be made even if your methods inside your TransactionScope block executed successfully.

What you need to do to work with System.Transactions

Add Reference
In order to work your modified code, you need to add reference of System.Transactions namespace by right clicking on your project's bin folder and selecting Add Reference ... When you do that your web.config file Compilation section will be modified something like this


- Hide Code
<compilation>

<assemblies>
<add assembly="System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>


Start Distributed Transaction Coordinator service
You need to start the Distributed Transaction Coordinator service on your server (or machine you are working on) by going through START > SETTINGS > CONTROL PANEL > ADMINISTRATIVE TOOLS > SERVICES.


Conclusion

Using System.Transactions.TransactionScope we can call different methods of different classes within a scope and commits all changes once all methods executed successfully.

Hope this article looks interesting to you. If you have something to say, please feel free to write your feedback.

References:
http://msdn.microsoft.com/en-us/library/ms229977.aspx
http://msdn.microsoft.com/en-us/library/ms172152.aspx

Bookmark and Share

About Sheo Narayan

Experience:6 year(s)
Home page:http://sheonarayan.blogspot.com/
Member since:Tuesday, July 08, 2008
Biography:Throughout 1st in all educational exams.
Major qualifications: HDCS, BCA, ADCA, MCA
Locations: Hyderabad, India
 Latest post(s) from SheoNarayan

   ◘ SEO friendly pagination using asp:DataPager control posted on 8/18/2008 9:54:23 AM
   ◘ ListView Tips and Tricks posted on 8/14/2008 5:43:53 AM
   ◘ Working with HttpHandler in IIS 7 posted on 7/28/2008 3:56:22 PM
   ◘ Service Oriented Architecture, a real world example in ASP.NET with C# posted on 7/27/2008 1:20:50 PM
   ◘ Difference between asp:LinkButton, asp:ImageButton, asp:Button and asp:HyperLink control posted on 7/15/2008 9:25:51 AM


Question: Why to use www.dotnetfunda.com google search?
Answer: This search has been especially optimized to search technical articles. You may find to-the-point results in comparison with other search.
Google
About Us | Contact Us | Privacy Policy and Terms of Use | Link Exchange | Members | Go Top
All rights reserved to DotNetFunda.com. Logos, company names used here if any are only for reference purposes and they may be respective owner's right or trademarks.
This site is best viewed with a resolution of 1280x720 (or higher) and Microsoft Internet Explorer 6.0+ or Firefox 2.0+.