2

我使用 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。这是可能的还是完全错误的,我叫错了树?

提前致谢!

-担

4

1 回答 1

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 处理程序中提交。

于 2009-10-10T06:07:48.280 回答