使用StructureMap控制NHibernate ITransaction?

时间:2009-06-25 00:35:40

标签: nhibernate transactions structuremap

我使用StructureMap作为我的IoC容器,NHibernate作为我的ORM。我在网上找到了一个示例,展示了如何让StructureMap构建ISessionFactory和ISession,因此Factory是一个单例,Session是基于HttpContext的。这很好用,但后来我开始使用NH Profiler告诉我应该总是明确地使用Transactions。所以,我想,为什么不让StructureMap为我处理呢?使用下面的代码,我得到了所有工作正常,除了,我不知道如何/在哪里提交/回滚我的交易。

以下是我初始化StructureMap的方法:

    ObjectFactory.Initialize(x =>
    {
        x.ForRequestedType<ISessionFactory>()
            .CacheBy(InstanceScope.Singleton)
            .TheDefault.Is.ConstructedBy(cfg.BuildSessionFactory);

        x.ForRequestedType<ISession>()
            .CacheBy(InstanceScope.Hybrid)
            .TheDefault.Is.ConstructedBy(context => context.GetInstance<ISessionFactory>().OpenSession());

        x.ForRequestedType<ITransaction>()
            .CacheBy(InstanceScope.Hybrid)
            .TheDefault.Is.ConstructedBy(context => context.GetInstance<ISession>().BeginTransaction());

        x.Scan(y =>
        {
            y.TheCallingAssembly();
            y.WithDefaultConventions();
        });
    });

我的所有存储库如下所示:

    public UserRepository(ISession session, ITransaction transaction)
    {
        _session = session;
        _transaction = transaction;
    }

存储库中的典型方法如下:

    public void Remove(int id)
    {
        Remove(_session.Get<User>(id));
    }

我要做的是让我在一个HttpContext中调用的所有方法共享相同的Session和Transaction。这是可能还是这完全错了,我正在咆哮错误的树?

提前致谢!

-Dan

1 个答案:

答案 0 :(得分:2)

这个问题就是为什么我创建了一个结合了ISession和ITransaction的简单UnitOfWork。

在测试中,我会写下面的代码:

var product = new Product {Name = "Apple", Category = "Fruits"};
using (var session = _sessionFactory.OpenSession())
using (var transaction = _session.BeginTransaction())
{
    session.Save(product);
    transaction.Commit();
}

当我真的想要的时候:

var product = new Product {Name = "Apple", Category = "Fruits"};
using (var unitOfWork = new UnitOfWork(_sessionFactory))
{
    unitOfWork.CurrentSession.Save(product);
    unitOfWork.Commit();
}

这是我的工作单元实施,

using NHibernate;

namespace NHibernateBootstrap.Core.Persistence
{
    public class UnitOfWork : IUnitOfWork
    {
        private readonly ISessionFactory _sessionFactory;
        private readonly ITransaction _transaction;

        public UnitOfWork(ISessionFactory sessionFactory)
        {
            _sessionFactory = sessionFactory;
            CurrentSession = _sessionFactory.OpenSession();
            _transaction = CurrentSession.BeginTransaction();
        }

        public ISession CurrentSession { get; private set;}

        public void Dispose()
        {
            CurrentSession.Close();
            CurrentSession = null;
        }

        public void Commit()
        {
            _transaction.Commit();
        }
    }
}

至于何时调用Commit()(使用ITransaction或UnitOfWork),我相信它应该在您的请求结束之前明确地完成。如果你不调用它,那么UnitOfWork应该自我清理,但不能提交。或者,您可以使用HttpModule在EndRequest处理程序中提交。