Question

I'm new to NHibernate but familar with EF4.

In a new business app with a new company, we've been instructed to use ASP.NET webforms and NHibernate, and I'm looking to get started. I had planned to keep things nice and simple, and structure things as follows:

  • Code-behinds calling Business Tier methods
  • Business Tier classes taking "IRepository" references in the constructor, to faciliate unit testing
  • Business Tier classes calling Repository methods, which return DTOs/collections of DTOs
  • The Repositories would hide/encapsulate all the NHibernate stuff.

In terms of managing sessions/transactions, it hasn't been as easy as I expected :)

Sessions: this approach (using Application_BeginRequest and Application_EndRequest in global.asax) looks like the easiest way (I think?).... though I hadn't expected to have to put NHibernate code in my UI tier.

Now how to use those Sessions.....

This "best practices" article suggests I use this pattern for all NHibernate data access (even reads):

using (ITransaction tx = Session.BeginTransaction())
{
    // execute a query, before an update, etc
    tx.Commit();
} 

So my questions are:

  • In my repositories, can I (and should I?) retrieve the current NHibernate session from HttpContext, as (I think) is suggested in this approach ? Doesn't seem right to me, as it is very UI-dependent.

(However that seems better to me than passing an NHibernate ISession object into the appropriate constructor, as I have seen used elsewhere.... i.e. in my case, I'd have to pass it from the UI through to the Business Tier constructor, then through to the Repository constructor.... and I'd hoped that the UI and Business Tier would be unaware of NHibernate.)

  • In my situation, do I really need to wrap all my reads in a transaction?

  • Is an "NHibernate" transaction any different to a "System.Transactions" transaction?

Was it helpful?

Solution

In a sense BeginRequest()/EndRequest() isn't really your UI code, but more of an "application-framework-kind-of-thing" that follows from how "requests" are handled in that particular style of application. If you want to reuse the same business tier in e.g. a native windows application you might want to handle your sessions differently, so it would not necessarily be a good idea to hide this completely in some sort of data layer.

You should likely use NHibernate's support for contextual sessions to track the active session per request. In your case, the WebSessionContext. http://nhibernate.info/doc/nh/en/index.html#architecture-current-session (Forget about ManagedWebSessionContext, it is deprecated.) Following this, you business/data layer will get the session from sessionFactory.GetCurrentSession(), and not depend on UI code.

Your UI should probably mostly be unaware of NH, except for application setup code in Global.asax. You can also move it to its own IHttpModule. You can of course hide it behind MyDataLayer.StartSession() if you really want to.

You should always use a transaction. What would you gain by not defining one? The database will still use (multiple) implicit transactions.

NHibernate transactions and System.Transaction are different. You can use TransactionScope, but you must in that case also use NH's transaction to avoid some problems.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top