NHibernate Repository类 - 1.处理事务处理| 2.如何初始化会话

时间:2011-10-31 11:07:04

标签: nhibernate session transactions repository

您好我开始学习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());

1 个答案:

答案 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操作开始时创建会话(并注入到存储库中),并将其与存储库一起处理当它结束时。