使用Castle AutoTx Facility和NHibernate Facility的交易

时间:2011-12-11 20:34:07

标签: .net nhibernate transactions castle-windsor windsor-nhfacility

我尝试将Castle NHibernate Facility与AutoTx工具一起使用。作为测试,我在服务中间抛出异常,以确保事务被回滚。但是,数据仍然存在于数据库中。

我的服务界面IActivityService使用TransactionAttribute:

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

CreateActivity的实施。我在这里抛出异常,希望回滚AddActivity中添加的数据:

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

AddActivity的实施。 SessionManager是注入ISessionManager

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

最后,我们是如何配置windsor容器的。 NHibernateInstaller直接来自the guide,我的流利的nhibernate配置交换进来:

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

配置似乎相当简单,但我无法弄清楚我错过了什么。谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

首先,您必须在会话管理器和活动服务之间具有直接依赖关系。应将会话管理器注入活动服务。只有在这种情况下,工具才会影响NHibernate事务。

    [Transactional]
    public class ActionService : IActionService
    {
        private ISessionManager _sessionManager;

        [Transaction]
        public void AddActivity(Activity activity)
        {
            using (ISession session = _sessionManager.OpenSession())
            {
                using (ITransaction tran = session.BeginTransaction())
                {
                        session.Save(activity);
                    tran.Commit();
                }
            }       
        }
        public ActionService(ISessionManager sessionManager)
    {
            _sessionManager = sessionManager;       
        }
    }
    _container.Register(Component.For<IActionService>()
            .ImplementedBy<ActionService>.LifestylePerWebRequest());

同时检查您是否对SessionManager,Server,DAO和其他依赖对象使用相同的生活方式。

答案 1 :(得分:1)

您没有显示服务实现类的类声明代码,因此您可能已经完成了此操作,但如果您需要声明性事务,则需要使用[Transactional]属性注释事务类。

[Transactional]    
public class ActivityServiceImpl {

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

如果在实现类中不包含[Transactional]属性,则AutoTx工具不知道为该类创建包装器。

我倾向于将[Transaction]属性放在实现方法上,而不是在接口定义中。我不知道它是否可以注释接口方法声明。

您可能还需要尝试一件事。我注意到在配置容器时,首先安装,然后添加AutoTx工具。我认为您应该在调用安装程序之前先添加设施。