Playing with System.Transactions...

Ahead of the horror of tomorrow…here’s a little class I was playing with as a demo, let me know what you think (it’s partially based on this example)

using System;

using System.Collections.Generic;

using System.Text;

using System.Transactions;

using System.Collections;

namespace TransTest

{

    public class TransactedHashtable : Hashtable, IEnlistmentNotification, ISinglePhaseNotification, IPromotableSinglePhaseNotification

    {

        Transaction transaction;

 

        Hashtable holdingTable;

        public TransactedHashtable()

        {

            Enlist();

            holdingTable = new Hashtable();

        }

 

        void Enlist()

        {

 

            transaction = Transaction.Current;

            if (transaction != null)

                transaction.EnlistVolatile(this, EnlistmentOptions.None);

        }

        public override void Add(object key, object value)

        {

            if (transaction == null || transaction != Transaction.Current) Enlist();

            holdingTable.Add(key, value);

        }

 

 

        void OnCommit()

        {

            foreach (DictionaryEntry de in holdingTable)

            {

                base[de.Value] = de.Value;

            }

            holdingTable.Clear();

        }

 

        #region IDisposable Members

 

        public void Dispose()

        {

            base.Clear();

        }

 

        #endregion

 

        #region IEnlistmentNotification Members

 

        public void Commit(Enlistment enlistment)

        {

            OnCommit();

            enlistment.Done();

        }

 

        public void InDoubt(Enlistment enlistment)

        {

 

        }

 

        public void Prepare(PreparingEnlistment preparingEnlistment)

        {

            preparingEnlistment.Prepared();

            //preparingEnlistment.Done();

        }

 

        public void Rollback(Enlistment enlistment)

        {

            holdingTable.Clear();

        }

 

        #endregion

 

        #region ISinglePhaseNotification Members

 

        public void SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment)

        {

            OnCommit();

            singlePhaseEnlistment.Committed();

        }

 

        #endregion

 

        #region IPromotableSinglePhaseNotification Members

 

        public void Initialize()

        {

        }

 

        public Transaction Promote()

        {

            return transaction.Clone();

        }

 

        public void Rollback(SinglePhaseEnlistment singlePhaseEnlistment)

        {

            this.holdingTable.Clear();

        }

 

        #endregion

    }

}

using System;

using System.Collections.Generic;

using System.Text;

using System.Transactions;

using System.Collections;

using System.Data.SqlClient;

 

namespace TransTest

{

    class Program

    {

        static void Main(string[] args)

        {

 

 

 

            TransactedHashtable t = new TransactedHashtable();

 

            using(TransactionScope ts = new TransactionScope())

            {

                using (SqlConnection conn = new SqlConnection("database=Northwind;data source=127.0.0.1;Integrated Security=SSPI;"))

                {

                    conn.Open();

                    SqlCommand comm = new SqlCommand("UPDATE    Customers SET City = 'New York' WHERE    (CustomerID = 'ALFKI')");

                    comm.Connection = conn;

                    comm.ExecuteNonQuery();

                }

                t.Add("aaaaa", "aaa");

                t.Add("bbbbb", "bbb");

                ts.Complete();

            }

 

            foreach(DictionaryEntry de in t )

            {

                Console.WriteLine(de.Key.ToString() + " :: " + de.Value.ToString());

            }

 

            using (TransactionScope ts = new TransactionScope())

            {

                using (SqlConnection conn = new SqlConnection("database=Northwind;data source=127.0.0.1;Integrated Security=SSPI;"))

                {

                    conn.Open();

                    SqlCommand comm = new SqlCommand("UPDATE    Customers SET City = 'Berlin' WHERE    (CustomerID = 'ALFKI')");

                    comm.Connection = conn;

                    comm.ExecuteNonQuery();

                }

                t.Add("ccccc", "ccc");

                t.Add("ddddd", "ddd");

                //ts.Complete();

            }

 

            foreach (DictionaryEntry de in t)

            {

                Console.WriteLine(de.Key.ToString() + " :: " + de.Value.ToString());

            }

            Console.ReadLine();

        }

    }

}


Since the second add block doesn’t commit the transaction, it’s not committed (and rolled back…which just means I don’t add them to the hashtable in this instance). Anyway, I thought it was a nice little example…opinions???

UPDATE: Very much a work in progress (since there's virtually no documentation on how to do this yet), just updated this to support promotion, the above example just uses the SQL connections to force promotion to the OLETx Manager (using MSDTC)...suspect this will become pretty common in the years to come :0)

Print | posted @ Monday, April 18, 2005 11:46 AM

Comments on this entry:

No comments posted yet.

Your comment:

Title:
Name:
Email:
Website:
 
Italic Underline Blockquote Hyperlink
 
 
Please add 4 and 1 and type the answer here: