.netnhibernatetransactionscastle-windsorwindsor-nhfacility

Transactions using Castle AutoTx Facility and NHibernate Facility


I'm trying to use the Castle NHibernate Facility with the AutoTx Facility. As a test, I'm throwing an exception in the middle of my service, to make sure the transaction is rolled back. However, the data is still persisted in the database.

My service interface, IActivityService using the TransactionAttribute:

public interface IActivityService
{
    [Transaction]
    Activity CreateActivity(Activity activity);
}

The implementation of CreateActivity. I'm throwing an exception here, expecting the data added in AddActivity to be rolled back:

public virtual Activity CreateActivity(Activity activity)
{
    activityDAO.AddActivity(activity);
    throw new Exception("This should rollback the transaction");
    return activity;
}

Implementation of AddActivity. SessionManager is an injected ISessionManager.

public void AddActivity(Activity activity)
{
    using (ISession session = SessionManager.OpenSession())
    {
        session.Save(activity);
    }
}

Finally, here's how I'm configuring the windsor container. The NHibernateInstaller is straight from the guide, with my fluent nhibernate configuration swapped in:

container = new WindsorContainer().Install(FromAssembly.This());

// set up ISessionManager injection for DAOs
container
    .AddFacility<AutoTxFacility>()
    .Register(Component
        .For<INHibernateInstaller>()
        .ImplementedBy<NHibernateInstaller>()
        .LifeStyle.Singleton)
    .AddFacility<NHibernateFacility>(f => 
        f.DefaultLifeStyle = DefaultSessionLifeStyleOption.SessionPerWebRequest);

The configuration seemed fairly straightforward, but I can't figure out what I'm missing. Thanks for any help.


Solution

  • You do not show the class declaration code for the service implementation class, so you might have already done this, but if you want declarative transactions, you need to annotate the transaction class with the [Transactional] attribute.

    [Transactional]    
    public class ActivityServiceImpl {
    
        [Transaction]
        public Activity CreateActivity(Activity activity) {
            // ... implementation here
        }
    }
    

    If you do not include the [Transactional] attribute on the implementing class, the AutoTx facility does not know to create a wrapper for the class.

    I tend to put the [Transaction] attribute on the implementing method, not in the interface definition. I don't know if it works annotating the interface method declaration.

    One more thing you might need to try. I notice that when you are configuring your container, you are installing first, and then adding the AutoTx facility. I think you should add the facilities first before invoking your installers.