Skip to content

Transaction attribute (supports nhibernate or system.transaction. works with asp.net, wcf, windows gui and windows service applications)

Seif Attar edited this page Feb 14, 2012 · 3 revisions

The Transaction attribute described here uses Castle Interceptors. You need to setup your application to use Contrib's Castle Windsor facilities before proceeding.

You will need to reference the following DLLs in any project that uses Transaction attribute:

SharpArchContrib.Castle.dll
SharpArchContrib.Data.dll

Why Use the Transaction Attribute? (The Argument for AOP)

Transactions are a key feature of almost any application that works with a database. Typically, you have to have put code like the following in any method that will work with transactions:

NHibernateSession.CurrentFor(factoryKey).Transaction.Begin();
try {
    //application logic here
    NHibernateSession.CurrentFor(factoryKey).Transaction.Commit();
} catch {
    NHibernateSession.CurrentFor(factoryKey).Transaction.Rollback();
}

Unfortunately, this logic is repetitive and obscures the application logic. Of course, S#arp Architecture has its own Transaction attribute. As good as it is, it won't work in Windows applications. It also is not capable of working in concert with Microsoft's System.Transaction transactions (TransactionScopes). S#arp Architecture Contrib's Transaction attribute takes care of all of this.

Basic S#arp Architecture Contrib Transactions

Using transactions in any application is as simple as putting the SharpArchContrib.Castle.NHibernate.Transaction attribute on your method as shown in the following example:

[Transaction]
public void DoTransaction() {
    //do some work here
}

Transactions can be nested and the work properly. For example:

[Transaction]
public void DoTransaction() {
    //do some work here
    DoInnerPortion();
}

[Transaction]
public void DoInnerPortion() {
    //do some more work here
}

Nested transactions work as one unit. If rollback occurs at any point in the transaction (e.g. an unhandled exception occurs), the entire transaction gets rolled back. If no exception occurs, the transaction is committed when the outermost scope completes.

Generally, exceptions that cause a rollback bubble-up to the caller. The only exception is the SharpArchContrib.Data.NHibernate.AbortTransactionException. Throwing this in a method attributed with the Transaction attribute will force a rollback without passing the exception up to the caller. For example:

[Transaction]
public void DoTransaction() {
    //do some work here
    if (someCondition) {
        //force rollback
        throw new AbortTransactionException();
    }
}

Integration with System.Transaction (TransactionScope)

As described in configure your application to use Castle Windsor, you can configure the Transaction attribute to use either standard NHibernate transactions or Microsoft's System.Transaction.TransactionScope. When using TransactionScope, the transaction attribute disconnects the NHibernate session, enters a transaction scope and then reconnects the NHibernate session. This allows the underlying ADO.NET connection to enlist in the transaction. There is not a large cost to this since in most cases a new database connection is not actually required. Instead, an existing connection comes out of the connection pool.

To use the SystemTransactionManager add the type to the call registering the Contrib components:

IWindsorContainer container = new WindsorContainer();
SharpArchContrib.Castle.CastleWindsor.AddComponentsTo(container, typeof(SystemTransactionManager));