您好我开始学习NHibernate,现在我正在尝试为NHibernate创建自己的存储库类。
我发现了很多关于这个主题的文章。我选择了这个教程:http://dotnetslackers.com/Community/blogs/antrad/archive/2008/10/25/about-repository-pattern-and-nhibernate.aspx
我很少混淆如何处理存储库中的事务。
我有存储库界面:
public interface IRepository<T> where T : class
{
void Commit();
void RollBack();
void BeginTransaction();
//...
}
我的问题是为什么在存储库的构造函数类中有良好的开始事务。
这部分代码来自博客。
public class NHibRepository<T> :IRepository<T>
where T : class
{
#region Private fields
private ISession _session;
#endregion
#region Constructor
public NHibRepository(ISession session)
{
_session = NHibernateSessionManager.Instance.GetSession();
//why begin transaction where???
_session.BeginTransaction();
}
#endregion
#region Trans
public void Commit()
{
if (session.Transaction.IsActive)
{
session.Transaction.Commit();
}
}
public void Rollback()
{
if (session.Transaction.IsActive)
{
session.Transaction.Rollback();
session.Clear();
}
}
public void BeginTransaction()
{
Rollback();
session.BeginTransaction();
}
#endregion
}
我更新了此存储库,现在我使用此解决方案:
public class NHibRepository<T> :IRepository<T>
where T : class
{
#region Private fields
private ISession _session;
#endregion
#region Constructor
public NHibRepository(ISession session)
{
_session = session;
}
#endregion
#region Trans
public void Commit()
{
using (var trans=_session.BeginTransaction())
{
trans.Commit();
}
}
public void RollBack()
{
using (var trans = _session.BeginTransaction())
{
trans.Rollback();
}
}
public void BeginTransaction()
{
throw new NotImplementedException();
}
#endregion
}
我的第一个问题是哪种解决方案更好,为什么?或者为什么是正确的?
我的第二个问题是如何打开存储库类的会话,现在我使用这个帮助程序类:
public class NHibeHelper
{
private static ISessionFactory _sessionFactory;
private static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
InitializeSessionFactory();
return _sessionFactory;
}
}
private static void InitializeSessionFactory()
{
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(
@"Server=Zues\SQLEXPRESS;Database=TEST;Trusted_Connection=True;")
)
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<UserMap>().Conventions.Add(DefaultCascade.All()))
.ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(true, true))
.BuildSessionFactory();
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
像这样使用:
_userRepo = new NHibRepository<User>(NHibeHelper.OpenSession());
答案 0 :(得分:1)
查看您为事务管理提供的两个选项,它们实际上都存在问题。
在示例1中,事务不一定要处理,并且您还要将事务的生命周期链接到存储库的生命周期。这不一定是坏事,但除非您使用IoC容器或其他方法来确保为每个数据库操作重新创建存储库,否则您只能提交一次,后续提交可能会失败。 / p>
遗憾的是,示例2根本不起作用 - 在Commit / RollBack中,每次都要启动一个新事务。特别是在RollBack的情况下,如果在事务的上下文中从外部代码调用它,您将要做的就是启动一个新的嵌套事务,然后立即回滚它。不幸的是,它不是很有用。
我对您的第一个问题的个人解决方案是使用System.Transactions中的环境事务将事务管理从存储库中拉出来。这样,您仍然可以进行分离,因为环境事务与提供程序无关,而且您可以更好地控制可能执行的许多存储库操作将涉及事务,而不是始终使用每个操作的单个事务模型。有关详细信息,请参阅http://msdn.microsoft.com/en-us/magazine/cc163527.aspx。
至于你的第二个问题,我强烈建议你查看像温莎城堡或Unity这样的IoC容器。你所拥有的助手类远比重建会话工厂好得多,但是通过使用IoC容器,你可以非常轻松地确保会话对象的生命周期正是你想要的。例如,在我正在处理的许多WCF Per-Call服务中,我使用Castle Windsor来确保在WCF操作开始时创建会话(并注入到存储库中),并将其与存储库一起处理当它结束时。