Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

A Transactional Repository Implementation in .NET

, 26 Nov 2008
A Transactional Enterprise Caching Application Block implementation.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Transactions;

namespace CachingAppBlock.Transactional
{
    /// <summary>
    /// Transactional lock class is solely used for thread synchronization
    /// </summary>
    public class TransactionalLock
    {
        private static readonly ThreadSafeDictionary<string, TransactionalLock> lockDictionary = new ThreadSafeDictionary<string, TransactionalLock>();

        private Synchronizer threadSynchronizer = new Synchronizer();
        private TransactionInformation tranInfo;

        public static void Lock(string key)
        {
            if (Transaction.Current != null)
            {
                if (!lockDictionary.ContainsKey(key))
                {
                    lockDictionary[key] = new TransactionalLock();
                }
                lockDictionary[key].LockInternal();
            }
        }
        
        
        private void LockInternal()
        {
            if (tranInfo == null)
            {
                InitializeLock();
            }
            if (!TransactionsEqual(Transaction.Current.TransactionInformation, tranInfo))
            {
                threadSynchronizer.Wait();
                InitializeLock();
            }
        }

        private void InitializeLock()
        {
            if(Transaction.Current.IsolationLevel != IsolationLevel.Serializable)
            {
                throw new InvalidOperationException("Only serializable transactions are supported");
            }
            
            tranInfo = Transaction.Current.TransactionInformation;
            
            Transaction.Current.TransactionCompleted +=
                (object sender, TransactionEventArgs e) => {
                    threadSynchronizer.Set();
                };
            
        }

        private static bool TransactionsEqual(TransactionInformation tran1, TransactionInformation tran2)
        {
            if (tran1.DistributedIdentifier == Guid.Empty && tran1.DistributedIdentifier == Guid.Empty)
            {
                return tran1.LocalIdentifier == tran2.LocalIdentifier;
            }
            return tran1.DistributedIdentifier == tran2.DistributedIdentifier;
        }

        private class Synchronizer
        {
            private object lockObject = new object();
            private bool canProceed = false;

            public void Wait()
            {
                lock (lockObject)
                {
                    while (!canProceed) Monitor.Wait(lockObject);
                    canProceed = true;
                }
            }

            public void Set()
            {
                lock (lockObject)
                {
                    canProceed = true;
                    Monitor.Pulse(lockObject);
                }
            }
        }

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Vitaliy Liptchinsky
Technical Lead bwin Interactive Entertainment AG
Austria Austria
The views expressed in my articles are mine and do not necessarily reflect the views of my employer.
 
if(youWantToContactMe)
{
SendMessage(string.Format("{0}@{1}.com", "liptchinski_vit", "yahoo"));
}
 
More info in my LinkedIn profile:
http://www.linkedin.com/in/vitaliyliptchinsky

| Advertise | Privacy | Mobile
Web01 | 2.8.140926.1 | Last Updated 26 Nov 2008
Article Copyright 2008 by Vitaliy Liptchinsky
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid