我使用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
答案 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处理程序中提交。