I recieved a request for some info on rolling back transactions and a litle more basic information.  I hope this helps...if not, let me know and I will add more:)

Committing and Rolling Back Transactions:

After Transactions are created, they can either committed or rolled back.  The process is the same for database and not-database related routines.  There is no concept of save points, so if the transaction rolls back, it will always be completely rolled back.

Implicit Programming Model for Transactions:

System.Transactions provides two programming models for creating Transactions; an implicit model and an explicit model.  With the implicit model, you create TransactionScopes and the TransactionScopes takes care of creating the transaction, setting the Transaction as the ambient transaction that will be used by transacted resource managers such as SQL, and committing/aborting the Transaction.  This implicit model is the recommended way to use Transactions as it is easy to use and requires less work on the part of the developer.  When you instantiate a new TransactionScope, the scope will determine if a new transaction needs to be created and will create one for you if necessary.  Then, at the end of the scope, you must call the Complete method on the TransactionScope to inform the transaction manager that it is acceptable to commit the transaction.  It is good practice to put the call to Complete as the last statement in the using block.  If you want to rollback the transaction, you should let the scope end without calling the Complete method.  One way to do this is to throw an exception inside the scope and the scope will automatically roll the transaction back for you. 

using (TransactionScope ts = new TransactionScope())
{
   // Do Database or Non-Database transacted work

    // If you create a connection to a SQL database here, SQL will automatically enlist in the TransactionScope’s transaction

     //Call complete on the TransactionScope or not based on input
    ConsoleKeyInfo c;
    while (true)
    {
       Console.Write("Complete the transaction scope? [Y|N] ");
        c = Console.ReadKey();
        Console.WriteLine();
        if ((c.KeyChar == 'Y') || (c.KeyChar == 'y'))
        {
            // Commit the transaction
            ts.Complete();
            break;
        }
        else if ((c.KeyChar == 'N') || (c.KeyChar == 'n'))
        {
            // This will rollback the transaction because you are exiting the scope without calling ts.Complete();
            break;
        }
    }
}

 

Explicit Programming Model for Transactions:

The CommittableTransaction class provides an explicit way for applications to use a transaction, as opposed to using the TransactionScope class implicitly. It is useful for applications that want to use the same transaction across multiple function calls or multiple thread calls. Unlike the TransactionScope class, the application writer needs to specifically call the Commit and Rollback methods in order to commit or abort the transaction.

You should note the followings when working with the CommittableTransaction class,

-         Creating a CommittableTransaction transaction does not set the ambient transaction. You need to specifically set and reset the ambient transaction, to ensure that resource managers operate under the right transaction context when appropriate. The way to set the current ambient transaction is by setting the static Current property on the global Transaction object.

-         A CommittableTransaction object cannot be reused. Once a CommittableTransaction object has been committed or rolled back, it cannot be used again in a transaction. That is, it cannot be set as the current ambient transaction context. 

 

//Create a committable transaction
CommittableTransaction tx = new CommittableTransaction();

// Do Database or Non-Database transactional work 

// If you create a database connection here, you will have to explicitly enlist in the connection using something like: myConnection.EnlistTransaction(tx);
// Commit or rollback the transaction
while (true)
{
    Console.Write("Commit or Rollback? [C|R] ");
    ConsoleKeyInfo c = Console.ReadKey();
    Console.WriteLine();
    if ((c.KeyChar == 'C') || (c.KeyChar == 'c'))
    {
        tx.Commit();
        break;
    }
    else if ((c.KeyChar == 'R') || (c.KeyChar == 'r'))
    {
        tx.Rollback();
        break;
    }
}
tx = null;