Click here to Skip to main content
Licence 
First Posted 19 Nov 2007
Views 13,611
Downloads 96
Bookmarked 25 times

A customized business transaction in C#

By | 19 Nov 2007 | Article
An article on implementing a customized business transaction class based on LLBLGen Pro.

Introduction

In every project we need a business transaction class which help us to control our business flow. This class should be able to handle nested transactions too. I wrote a class, named "BusinessTransaction" and want to share it here with every one who has problem with nested transaction handling.

Background

In many situations we have some Services/Facades/Managers which process data containers and save them in database. Sometime these services call each other too, in these cases if any exception occur in inner service, the exception is thrown in a 2 level transaction and both of them should be rolled back.

For example, in an algorithm like this,

public void X() 
{     
   try    
   {    
      transaction.Start();         
      console.WriteLine("X");
      transaction.Commit();
    }     
    catch(Exception ex) 
    { 
        transaction.Rollback();        
        throw ex;    
    }
} 
public void Y() 
{     
   try    
   {    
      transaction.Start();
      console.WriteLine("Y");
      transaction.Commit();
    }     
    catch(Exception ex) 
    { 
        transaction.Rollback();        
        throw ex;    
    }
}  
public void Z() 
{     
   try    
   {    
      transaction.Start();         
      X();
      Y();
      transaction.Commit();
    }     
    catch(Exception ex) 
    { 
        transaction.Rollback();        
        throw ex;    
    }
} 

We can have some cases such as:

1- An Exception occurs between X transaction: X and Z should be rolled back.

2- An Exception occurs after X commit and between Y transaction: X,Y and Z should be rolled back.

3- An Exception occurs After X commit and between Y transaction, but Y doesn't throw it: Only Y should be rolled back, X and Z must be committed.

4- An Exception occurs After Y commit: X,Y and Z should be rolled back.

So, i tried to handle all of these manners in my code and tested them; it worked!
I always use LLBLGen Pro. as ORM and of course you can see it in my code, but if you are not familiar with it, don't worry, the related code is easy to understand!

Using the code

I used a stack to handle nested transactions. In every Start() Method, the related transaction identifier is pushed in it, only if the stack is empty, it means that no outer transaction exists, so i starts a real transaction.

    /// <summary>
        /// starts a new Transaction or an inner Transaction
        /// </summary>
        /// <param name="isolationLevel"></param>
        public void Start(IsolationLevel isolationLevel)
        {
            string startMethodName = GetSavePoint();
            int transactionID = tarnsactionIDToInfoMap.Count + 1;

            if (transactionStack.Count == 0)
            {
                adapter.StartTransaction(isolationLevel, "1");
                tarnsactionIDToInfoMap.Clear();
            }
            else
            {
                adapter.SaveTransaction(transactionID.ToString());
            }

            tarnsactionIDToInfoMap.Add(transactionID, startMethodName);
            transactionStack.Push(transactionID);
        }

When commit() or rollback() are called, one transaction is popped, and again if stack becomes empty, it means that the transaction is a real one and have to be rolled back or committed.

    /// <summary>
        /// Commits the mosty inner Transaction
        /// </summary>
        public void Commit()
        {
            if (transactionStack.Count == 0)
            {
                throw new FatalException("Error in transaction Handling. Commit on empty stack", true);
            }

            string commitMethodName = GetSavePoint();
            string srartMethodName = tarnsactionIDToInfoMap[(int)(transactionStack.Pop())].ToString();

            if (!commitMethodName.Equals(srartMethodName))
            {
                LogManager.Instance.WriteWarning("Unmatched transaction. " +
                    "The Start Transaction was called from " + srartMethodName +
                    " but it was commited in " + commitMethodName);
            }

            if (transactionStack.Count == 0)
            {
                adapter.Commit();
            }
        }

        /// <summary>
        /// Rolls back the mosty inner Transaction
        /// </summary>
        public void Rollback()
        {
            if (transactionStack.Count == 0)
            {
                throw new FatalException("Error in transaction Handling. Rollback on empty stack", true);
            }

            int transactionID = (int)(transactionStack.Pop());
            string rollbackMethodName = GetSavePoint();
            string startMethodName = tarnsactionIDToInfoMap[transactionID].ToString();

            if (!rollbackMethodName.Equals(startMethodName))
            {
                LogManager.Instance.WriteWarning("Unmatched transaction. " +
                    "The Start Transaction was called from " + startMethodName +
                    " but it was rolled back in " + rollbackMethodName);
            }

            if (transactionStack.Count == 0)
            {
                adapter.Rollback();
            }
            else
            {
                adapter.Rollback(transactionID.ToString());
            }
        } 
I hope this class be useful!


License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Chapooki

Web Developer

Iran (Islamic Republic Of) Iran (Islamic Republic Of)

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
Generalno bad but -> System.Transactions -> transactionscope Pinmemberfred_0074:38 19 Nov '07  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120517.1 | Last Updated 19 Nov 2007
Article Copyright 2007 by Chapooki
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid