Atomatic Transaction Handling With NHibernate

440 views
Skip to first unread message

Marko

unread,
Jul 17, 2009, 5:40:46 AM7/17/09
to Autofac
Hello!

I've written this piece of code that I use for transaction handling.
I think something like this should be a part of Autofac package.
Here's a start.

It uses UnitOfWork pattern (one transaction per request).
You just have to tag a method with [Transaction] attribute and that's
it. If that method calls another method with [Transaction] attribute
it's executed in the same transaction.

This is all the required code.

[global::System.AttributeUsage(AttributeTargets.Method)]
public class TransactionAttribute : Attribute
{
}

public class TransactionInterceptor :
Castle.Core.Interceptor.IInterceptor
{
private readonly ISession db;
private ITransaction transaction = null;

public FISInterceptor(ISession db)
{
this.db = db;
}

public void Intercept(IInvocation invocation)
{
bool isTransactional = IsTransactional(invocation.Method);
bool iAmTheFirst = false;

if (transaction == null && isTransactional)
{
transaction = db.BeginTransaction();
iAmTheFirst = true;
}

try
{
invocation.Proceed();

if (iAmTheFirst)
{
iAmTheFirst = false;

transaction.Commit();
transaction = null;
}
}
catch(Exception ex)
{
if (iAmTheFirst)
{
iAmTheFirst = false;

transaction.Rollback();
transaction = null;
}
throw ex;
}
}

private bool IsTransactional(MethodInfo mi)
{
var atr = mi.GetCustomAttributes(false);

foreach (var a in atr)
{
if (a is TransactionAttribute)
{
return true;
}
}

return false;
}
}

public class MyAutofacModule : Autofac.Builder.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterModule(new FlexibleInterceptionModule());
builder.Register<TransactionInterceptor>().ContainerScoped();

//NHibernate - ISessionFactory (Using Fluent.NHibernate)
builder.Register(x => Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005
.ConnectionString(c => c.FromConnectionStringWithKey
("ConnectionString")))
.Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<MyAutofacModule>())
.BuildSessionFactory())
.SingletonScoped();

//NHibernate - ISession
builder.Register(c => c.Resolve<ISessionFactory>().OpenSession
()).ContainerScoped();

//Services
builder.Register<MyServiceClass>().ContainerScoped().InterceptedBy
(typeof(TransactionInterceptor));
}
}

//USAGE
public class MyServiceClass
{
[Transaction]
public virtual int Something()
{
//.... some transactional code
}
}

Nicholas Blumhardt

unread,
Jul 17, 2009, 9:59:49 PM7/17/09
to aut...@googlegroups.com
Wow! Looks like you've brought all the right ingredients together - thanks for posting this.

If you're interested in contributing this to the Autofac NHibernate integration please let me know.

Cheers,

Nick

2009/7/17 Marko <marko.p...@gmail.com>

Marko

unread,
Jul 22, 2009, 8:57:31 AM7/22/09
to Autofac
You can add it to NHibernate integration.
Just put my name and e-mail somewhere.

On Jul 18, 3:59 am, Nicholas Blumhardt <nicholas.blumha...@gmail.com>
wrote:
> Wow! Looks like you've brought all the right ingredients together - thanks
> for posting this.
> If you're interested in contributing this to the Autofac NHibernate
> integration please let me know.
>
> Cheers,
>
> Nick
>
> 2009/7/17 Marko <marko.podgor...@gmail.com>

Nicholas Blumhardt

unread,
Jul 27, 2009, 9:48:53 PM7/27/09
to aut...@googlegroups.com
Thanks, I'll let you know it goes.

Nick

2009/7/22 Marko <marko.p...@gmail.com>
Reply all
Reply to author
Forward
0 new messages