NHIBernate ASP.NET Transaction Duration

Currently, in our ASP.NET application, we have 1 session per request and each time we download or update the object we create one transaction. See below:

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(); } } 

Obviously, this is not ideal, as it means that you create a new database connection every time you load or save an object, which is associated with performance overhead.

Questions:

  • If the object is already loaded into the 1st level cache will the Call GetTransaction () open the database connection? I suspect it will be ...
  • Is there a better way to deal with our transaction transaction management less and therefore less database connections?

Unfortunately, the application code is probably too mature to structure everything like this (using get and update all in one transaction):

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

Would it be a terrible idea to create one transaction per request and pass it at the end of the request? I assume the downside is that it connects one connection to the database, while operations without the database occur.

+4
source share
2 answers

One transaction per request is considered best practice with NHibernate. This template is implemented in Sharp Architecture .

But in the Nhibernate BeginTransaction() method, make an open connection to the database. The connection is opened upon the first query of real sql and closes immediately after the query is completed. Thus, Nhibernate maintains an open connection for several seconds to complete the request. You can check it with SQL Profiler.

In addition, NHiberante is always trying to use the Sql Servers connection pool and therefore opening your connection may not be so expensive.

+5
source

It would be a terrible idea to create one transaction per request and pass it at the end of the request

That would be horrible, but I think this is bad practice. If there is an error, and the transaction is rolled back, I would rather process it on the page, and then at the end of the request. I prefer to use one session for each request with as many transactions as I need during the request (usually one).

NHibernate is very conscientious about managing database connections, you don't need to worry about this in most cases.

I donโ€™t like your transaction logic, especially since you are killing a session if the transaction fails. And I'm not sure why you are calling SaveOrUpdateCopy. NHibernate will detect if the object should be persisted, so the IsPersisted check is probably not needed. I am using this template:

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

All Articles