Skip to main content

Unity Transaction Handler

This post is going to explain how to write a custom Entity Framework Transaction Handler using Microsoft Unity Container. Unity is a light weight dependency injection framework created by the Microsoft Enterprise Best Practices group that also allows optional type and instance interception. You can find all about Unity here.

The idea behind a Transaction Handler is to allow application developers to use consistent programming model of transaction management regardless of the underlying technology. As a long time Java programmer, I have seen the benefits of using Spring Framework's transaction management, and I wanted to apply the same programming model and approach to my recent .NET project.

Microsoft Unity version 2.0 at the time of this writing did not have an out of the box transaction handler that could easily integrate with Entity Framework unlike its Spring Framework counter part. This post is going to go into detail on how to configure Unity to declare a custom transaction handler. This post will not go into detail on how to configure Unity but will show you how you can enable Unity's interception support as it is needed for us to intercept our object and inject our transaction attributes.

Let's begin.

The first thing we have to do is to enable Unity's Interception capabilities. You can do this in two ways and it really depends on how you are wiring your Unity Container. I will show you both options.

public static void BuildUnityContainer(IUnityContainer container)
        {
            container.AddNewExtension<Interception>();
            container
                .Configure<Interception>()
                    .AddPolicy("BeginTransactionScopeSave")
                    .AddMatchingRule<MemberNameMatchingRule>("ServiceLayerMatchSave", new InjectionConstructor("Save*"))
                    .AddCallHandler<TransactionHandler>("TransactionHandler")
               .Container.Configure<Interception>()
                    .AddPolicy("BeginTransactionScopeClear")
                    .AddMatchingRule<MemberNameMatchingRule>("ServiceLayerMatchClear", new InjectionConstructor("Clear*"))
                    .AddCallHandler<TransactionHandler>("TransactionHandler")
               .Container.Configure<Interception>()
                    .AddPolicy("BeginTransactionScopeExecute")
                    .AddMatchingRule<MemberNameMatchingRule>("ServiceLayerMatchExecute", new InjectionConstructor("Execute*"))
                    .AddCallHandler<TransactionHandler>("TransactionHandler");
         }


The above code assumes you are wiring your container programmatically and you have access to IUnityContainer interface. The first line of code basically configures the container for Interception handling. The next lines of configuration basically adds an interception policy that uses a regular expression for matching method names and applies our TransactionHandler to matching endpoints. You can see that I have configured our TransactionHandler to be applied to methods that begin with "Save", "Clear" and "Execute".

Following configuration snippet can be used if you are wiring Unity declaratively.

<container>
<extension type="Interception"/>
<interception>
<policy name="BeginTransactionScopeSave">
<matchingRule name="ServiceLayerMatchSave" type="MemberNameMatchingRule">
<constructor>
<param name="nameToMatch" value="Save*"/>
</constructor>
</matchingRule>
<callHandler name="TransactionHandler" type="TransactionHandler, Core"></callHandler>
</policy>
</container>

Above configuration accomplishes what we accomplished with our programatic approach. It first enables the Interception extension for Unity and then declares a policy that uses a regular expression for matching method names to apply a provided custom TransactionHandler.

Following is the actual TransactionHandler definition.
 public class TransactionHandler : ICallHandler
    {
        public int Order { get; set; }
        private IUnitOfWork iUnitOfWork;

        public TransactionHandler(IUnitOfWork iUnitOfWork)
        {
            this.iUnitOfWork = iUnitOfWork;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            IMethodReturn returnMessage;

            using (TransactionScope scope = new TransactionScope())
            {
                //Use logging in production
                returnMessage = getNext()(input, getNext);
                //If Exception is thrown rollback
                if (returnMessage.Exception == null)
                {
                    iUnitOfWork.Commit();
                    scope.Complete();
                }
            }
            return returnMessage;
        }
    }


The above code uses Unit of Work pattern to get access to the underlying data access technology. You can see that this object implements the ICallHandler interface and provides the implementation of the Invoke method. It basically uses the TransactionScope and handle's the target object's method execution and depending on the target object's method execution result (exception vs no-exception), it commits the transaction to the database.

Comments