Click here to Skip to main content
15,891,253 members
Articles / Programming Languages / C#

Data Access and Transaction Handling Framework

Rate me:
Please Sign up or sign in to vote.
4.69/5 (107 votes)
13 Jan 200510 min read 925.5K   2.1K   282  
Generic data access component for different datasources, sprocs/SQL, implicitly propagated transactions, explicitly managed transaction contexts etc.
using System;
using System.Data;
using System.Collections;
using Framework.Transactions;
using System.EnterpriseServices;
using Framework.DataAccess.TransactionHandling;
using System.Runtime.Remoting.Messaging;

namespace Framework.DataAccess.TransactionHandling.ESTransactionHandler
{
	/// <summary>
	/// ESTransactionHandler handles TransactionContext events.
	/// Implementation using COM+ DTC Transactions.
	/// </summary>
	public class ESTransactionHandler : ITransactionHandler
	{
		private const string THREAD_CURRENT_CONTEXT__KEY = "DTCCK";

		static ESTransactionHandler()
		{

		}

		public ESTransactionHandler()
		{
			
		}

		private static ArrayList Contexts
		{
			get 
			{
				ArrayList contexts = CallContext.GetData(THREAD_CURRENT_CONTEXT__KEY) as ArrayList;
				if(contexts == null)
				{
					contexts = new ArrayList();
					CallContext.SetData(THREAD_CURRENT_CONTEXT__KEY, contexts);
				}
				return contexts;
			}
		}

		private static ESTransactionContext PeekLastContext()
		{
			return PeekContext(1);
		}

		private static ESTransactionContext PeekLastButOneContext()
		{
			return PeekContext(2);
		}

		private static ESTransactionContext PeekContext(int lastIndex)
		{
			if(Contexts.Count >= lastIndex)
				return (ESTransactionContext)Contexts[Contexts.Count - lastIndex];
			else
				return null;
		}

		#region ITransactionHandler Members

		public void HandleTCCreated(object sender, TCCreatedEventArgs args)
		{
			//attach to the event handlers of the newly created transaction context
			TransactionContext trCtx = args.Context;
			trCtx.StateChanged += new TCStateChangedEventHandler(HandleTCStateChangedEvent);
		}

		public void HandleTCStateChangedEvent(object sender, TCStateChangedEventArgs args)
		{
			TransactionContext trCtx = (TransactionContext)sender;

			ESTransactionContext currentDtrCtx = PeekLastContext();			

			//here check the event & commit/rollback etc
			switch(trCtx.State) 
			{
				case TransactionContextState.Entered:
					ESTransactionContext newDtrCtx = null;
					if(currentDtrCtx != null)
						newDtrCtx = currentDtrCtx.CreateContext(trCtx.Affinity);
					else
						newDtrCtx = CreateContext(trCtx.Affinity);

					Contexts.Add(newDtrCtx);
					break;

				case TransactionContextState.ToBeCommitted:
					currentDtrCtx.VoteComplete();
					break;

				case TransactionContextState.ToBeRollbacked:
					try 
					{ 
						currentDtrCtx.VoteAbort();
					}
					catch {}	//suppress CONTEXT_E_ABORTED exception for a parent ctx(better way?)
					break;

				case TransactionContextState.Exitted:
					Contexts.RemoveAt(Contexts.Count - 1);

					try 
					{ 
						currentDtrCtx.Exit(); 
						currentDtrCtx.Dispose();
					} 
					catch {}	//suppress CONTEXT_E_ABORTED exception for a parent ctx(better way?)
					break;

				default:
					throw new Exception("Unexpected TransactionContextState:" + args.FromState.ToString());
			}
		}

		public static ESTransactionContext CreateContext(TransactionAffinity affinity)
		{
			switch(affinity)
			{
				case TransactionAffinity.RequiresNew:
					return new RequiresNewTransactionContext();
					
				case TransactionAffinity.Required:
					return new RequiredTransactionContext();

				case TransactionAffinity.Supported:
					return new SupportedTransactionContext();

				case TransactionAffinity.NotSupported:
					return new NotSupportedTransactionContext();

				default:
					throw new TransactionContextException("Invalid affinity(" + affinity.ToString() + ". Mapping failed.");
			}
		}

		public IDbTransaction GetTransaction(string dataSourceName, IDbConnection con)
		{
			ESTransactionContext currentDtrCtx = PeekLastContext();
			if(currentDtrCtx != null)
				currentDtrCtx.OpenConnection(con);

			return null;
		}

		#endregion
	}


}

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 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


Written By
Web Developer
Austria Austria
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions