Vishwas Lele's WebLog

Fleeting thoughts...

  • FormsAuthentication and Cookie Persistence

    Why are there multiple ways to set cookie peristence for ASP.NET Forms authentication? Each of the following related methods [1] allows you affect the cookie expiration period.

  • Lightweight Transaction Manager

     

    For decades, Transactions have known to be a powerful mechanism for robust fault-tolerance. Unfortunately, Transactions are also notoriously expensive mechanisms to use. With Whidbey, Microsoft is hoping to change that perception by lowering the cost of using Transactions. This comes about through the introduction of Lightweight Transaction Manager (LTM) that is part of the System.Transaction namespace. LTM is a full fledged transaction manager for volatile resources. This means as long as the resource manager (RM) is non-durable or durable but within the same appdomain, LTM will own the transaction. This dramatically reduces the overhead in creating a transaction. If you do indeed include a persistent RM, a second RM (2PC scenario) ownership is automatically transferred to RM(SQL Server 2005) and MS DTC respectively.

    Here is an example of using LTM:

     

     

      TransactedHashtable t = new TransactedHashtable();

       using (TransactionScope ts = new TransactionScope())

       {

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

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

           ts.Consistent = true;

       }

     

    In the above code snippet,  the TransactionScope class is used to make the scope of the using statement transactional. At the very end of the code block we vote for the transaction outcome by setting the Consistency property to true or false. I will discuss the TransactedHashtable later but it would suffice to understand that this a Hashtable that is protected by a transaction. In other words, if at some point we determine that the transaction scope is inconsistent, all changes we have made up until that point are rolled back. This is of course a very simple example, but you relate how the error handling has been simplified by the use of transactions.

     

    TransactedHastable is not a new class provided the framework. In fact, it is class that I created by deriving from the System.Collections.HashTable class. Let us look at how easy it add transaction awareness to a given class. The key here is the Add operation. It determines if it object instance is part of a transaction context and if needed, it enlists the instance with the LTM.

     

    public class TransactedHashtable : Hashtable

    {

      private Hashtable m_Table;

      private ITransaction m_Tx;

      public TransactedHashtable()

      {

           m_Table = new Hashtable();

      }

      public override void Add(object key, object value)

      {

           m_Tx = Transaction.Current;

           if (m_Tx!=null && !m_Table.Contains(m_Tx.ToString()))

          {

              ISinglePhaseNotification singlePhaseNotification = new SinglePhaseNotification(this);

              m_Tx.VolatileEnlist(singlePhaseNotification, false);

              m_Table.Add(m_Tx.ToString(), m_Tx);

          }

          base.Add(key, value);

     }

      public override int Count

      {

           get

          {

               return base.Count;

           }

      }

      public void Dispose()

      {

           base.Clear();

      }

    }

     

     

    At the time of enlistment we need to pass as callback, an implementation of  the interface ISinglePhaseEnlistment. This allows us to receive notifications from the LTM. Here is a simplified implementation of ISinglePhaseEnlistment interface:

     

    public class SinglePhaseNotification : System.Transactions.ISinglePhaseNotification

    {

        TransactedHashtable m_Obj;

        public SinglePhaseNotification(TransactedHashtable t)

        {

            m_Obj = t;

        }

        void ISinglePhaseNotification.SinglePhaseCommit(ISinglePhaseEnlistment singlePhaseEnlistment)

        {

            singlePhaseEnlistment.Committed();

        }

        void IEnlistmentNotification.Commit(IEnlistment enlistment) { ;}

        void IEnlistmentNotification.InDoubt() { ;}

        void IEnlistmentNotification.Prepare(IPreparingEnlistment preparingEnlistment, byte[] recoveryInformation) { ;}

        void IEnlistmentNotification.Rollback(IEnlistment enlistment)

        {

           m_Obj.Dispose();

        }

     }