2010-09-29 57 views
4

当前在我们的ASP.NET应用程序中,每个请求有1个会话,并且每次我们加载或更新时都创建一个事务和对象。请看下图:ASP.NET NHibernate事务持续时间

public static T FindById<T>(object id) 
    { 
     ISession session = NHibernateHelper.GetCurrentSession(); 
     ITransaction tx = session.BeginTransaction(); 
     try 
     { 
      obj = session.Get<T>(id); 
      tx.Commit(); 
     } 
     catch 
     { 
      session.Close(); 
      throw; 
     } 
     finally 
     { 
      tx.Dispose(); 
     } 
     return obj; 
    } 

    public virtual void Save() 
    { 
     ISession session = NHibernateHelper.GetCurrentSession(); 
     ITransaction transaction = session.BeginTransaction(); 
     try 
     { 
      if (!IsPersisted) 
      { 
       session.Save(this); 
      } 
      else 
      { 
       session.SaveOrUpdateCopy(this); 
      } 
      transaction.Commit(); 

     } 
     catch (HibernateException) 
     { 
      if (transaction != null) 
      { 
       transaction.Rollback(); 
      } 
      if (session.IsOpen) 
      { 
       session.Close(); 
      } 
      throw; 
     } 
     finally 
     { 
      transaction.Dispose(); 
     } 

    } 

很明显,因为它意味着你创建的数据库每次加载或保存一个对象,这会带来性能开销时间一个新的连接,这是不理想的。

问题:

  • 如果一个实体在 1级高速缓存已加载将 GetTransaction()调用打开一个数据库连接 ?我怀疑它会...
  • 有没有更好的方式来处理我们的交易管理,所以 有更少的交易,因此 少数据库连接?

不幸的是,应用程序代码可能是太成熟了构建一切都像这样(与获得和更新都在同一个交易):

using(var session = sessionFactory.OpenSession()) 
using(var tx = session.BeginTransaction()) 
{ 
    var post = session.Get<Post>(1); 
    // do something with post 
    tx.Commit(); 
} 

难道是一个可怕的想法创造每一个交易在请求结束时请求并提交它?我认为它的缺点是它绑定了一个数据库连接,而非数据库操作发生。

+0

这是问了很多次... – Paco 2010-09-29 10:21:49

+0

道歉,我有同样的问题上SO一看,找不到任何东西。如果有相关的问题,请让我知道,我会链接到它 – 2010-09-29 10:30:53

回答

5

每个请求的一个事务被认为是NHibernate的最佳实践。该模式在Sharp Architecture中实施。

但在Nhibernate方法BeginTransaction()尝试打开连接到DB。在第一个真正的sql请求中打开连接并在执行查询后关闭。所以Nhibernate持有几秒钟的开放连接来执行查询。您可以通过SQL Profiler验证它。

此外,NHiberante总是尝试使用Sql Server连接池,并且为什么打开您的连接可能并不昂贵。

+1

你的意思是每个请求一个事务或每个请求一个会话是最佳实践?另外,我可以在Profiler中看到BeginTransaction调用OpenConnection,而不是实际的数据库调用。 – 2010-09-29 11:27:37

+0

我是指每个请求的交易。不知道关于不开始连接开始交易,也许你是对的。 – Sly 2010-09-29 11:35:09

2

难道是一个可怕的主意,以创建每个请求一个事务,并在请求

月底提交它,它不会是可怕的,但我认为这是一个贫穷的做法。如果出现错误并且事务回滚,我宁愿在页面上处理它,然后在请求结束时处理它。我希望在请求期间为每个请求使用一次会话,并根据需要使用尽可能多的事务(通常为一次)。

NHibernate对于管理数据库连接非常认真,在大多数情况下你不需要担心。

我不喜欢你的事务逻辑,特别是因为你在事务失败时终止会话。我不确定你为什么要调用SaveOrUpdateCopy。 NHibernate会检测对象是否需要保持,因此可能不需要IsPersisted检查。我用这个模式:

using (var txn = session.BeginTransaction()) 
{ 
    try 
    { 
     session.SaveOrUpdate(this); 
     txn.Commit(); 
    } 
    catch (Exception ex) 
    { 
     txn.Rollback(); 
     // log 
     // handle, wrap, or throw 
    } 
}