Is this a good solution to handle NHibernate Isession as PerWebRequest - nhibernate

I Have been struggeling with NHibernate session management and have now ended up with two possible solutions to meet a session per web request.
I'm using Windsor for IoC in an ASPNET mvc project
First solution is to open a session in begin_request and close/dispose it again in end_request. In Windsor setup I would have
container.Register(Component.For().UsingFactoryMethod(() => SessionFactory.GetCurrentSession()).LifeStyle.Transient;
This solution creates the session per request and shares it through GetCurrentSession.
The second solution is to use Windsor like
container.Register(Component.For().UsingFactoryMethod(() => SessionFactory.OpenSession()).LifeStyle.PerWebRequest);
This sould also give me an session per web request and support constructor injection. It's a bit more simpel, but I need a second opinion.
Please let me know what you would prefer to use,
best regards
Rasmus

I don't recommend any of those two solutions. Instead of trying to reinvent the wheel, use the NHibernate facility.

I use a unit of work, which I configure per web request in the container. The unit of work does not just create a session, but it also commits and rolls back transactions. The main reason to use a unit of work is to make the database more stable. More information about the unit of work pattern can be found on here.
public interface INHiberanteUnitOfWork
{
ISession session { get; }
void Commit();
void RollBack();
}

Related

ServiceStack and NHibernate Unit Of Work Pattern

Long story as brief as possible...
I have an existing application that I'm trying to get ServiceStack into to create our new API. This app is currently an MVC3 app and uses the UnitOfWork pattern using Attribute Injection on MVC routes to create/finalize a transaction where the attribute is applied.
Trying to accomplish something similar using ServiceStack
This gist
shows the relevant ServiceStack configuration settings. What I am curious about is the global request/response filters -- these will create a new unit of work for each request and close it before sending the response to the client (there is a check in there so if an error occurs writing to the db, we return an appropriate response to the client, and not a false "success" message)
My questions are:
Is this a good idea or not, or is there a better way to do
this with ServiceStack.
In the MVC site we only create a new unit
of work on an action that will add/update/delete data - should we do
something similar here or is it fine to create a transaction only to retrieve data?
As mentioned in ServiceStack's IOC wiki the Funq IOC registers dependencies as a singleton by default. So to register it with RequestScope you need to specify it as done here:
container.RegisterAutoWiredAs<NHibernateUnitOfWork, IUnitOfWork()
.ReusedWithin(ReuseScope.Request);
Although this is not likely what you want as it registers as a singleton, i.e. the same instance returned for every request:
container.Register<ISession>((c) => {
var uow = (INHibernateUnitOfWork) c.Resolve<IUnitOfWork>();
return uow.Session;
});
You probably want to make this:
.ReusedWithin(ReuseScope.Request); //per request
.ReusedWithin(ReuseScope.None); //Executed each time its injected
Using a RequestScope also works for Global Request/Response filters which will get the same instance as used in the Service.
1) Whether you are using ServiceStack, MVC, WCF, Nancy, or any other web framework, the most common method to use is the session-per-request pattern. In web terms, this means creating a new unit of work in the beginning of the request and disposing of the unit of work at the end of the request. Almost all web frameworks have hooks for these events.
Resources:
https://stackoverflow.com/a/13206256/670028
https://stackoverflow.com/search?q=servicestack+session+per+request
2) You should always interact with NHibernate within a transaction.
Please see any of the following for an explanation of why:
http://ayende.com/blog/3775/nh-prof-alerts-use-of-implicit-transactions-is-discouraged
http://www.hibernatingrhinos.com/products/nhprof/learn/alert/DoNotUseImplicitTransactions
Note that when switching to using transactions with reads, be sure to make yourself aware of NULL behavior: http://www.zvolkov.com/clog/2009/07/09/why-nhibernate-updates-db-on-commit-of-read-only-transaction/#comments

Managing NHibernate ISession with Autofac

Does anyone have any tips or best practices regarding how Autofac can help manage the NHibernate ISession Instance (in the case of an ASP.NET MVC application)?
I'm not overly familiar with how NHibernate sessions should be handled. That said, Autofac have excellent instance lifetime handling (scoping and deterministic disposal). Some related resources are this article and this question. Since you're in ASP.Net MVC land make sure you also look into the MVC integration stuff.
To illustrate the point, here's a quick sample on how you can use Autofac factory delegates and the Owned generic to get full control over instance lifetime:
public class SomeController
{
private readonly Func<Owned<ISession>> _sessionFactory;
public SomeController(Func<Owned<ISession>> sessionFactory)
{
_sessionFactory = sessionFactory;
}
public void DoSomeWork()
{
using (var session = _sessionFactory())
{
var transaction = session.Value.BeginTransaction();
....
}
}
}
The container setup to get this to work is quite simple. Notice that we don't have to do anything to get the Func<> and Owned<> types, these are made available automatically by Autofac:
builder.Register(c => cfg.BuildSessionFactory())
.As<ISessionFactory>()
.SingleInstance();
builder.Register(c => c.Resolve<ISessionFactory>().OpenSession());
Update: my reasoning here is that, according to this NHibernate tutorial, the lifetime of the session instance should be that of the "unit of work". Thus we need some way of controlling both when the session instance is created and when the session is disposed.
With Autofac we get this control by requesting a Func<> instead of the type directly. Not using Func<> would require that the session instance be created upfront before the controller instance is created.
Next, the default in Autofac is that instances have the lifetime of their container. Since we know that we need the power to dispose this instance as soon as the unit of work is done, we request an Owned instance. Disposing the owned instance will in this case immediately dispose the underlying session.
Edit: Sounds like Autofac and probably other containers can scope the lifetime correctly. If that's the case, go for it.
It isn't a good idea to use your IoC container to manage sessions directly. The lifetime of your session should correspond to your unit of work (transaction boundary). In the case of a web application, that should almost certainly be the lifetime of a web request.
The most common way to achieve this is with an HttpModule that both creates your session and starts your transaction when a request begins, then commits when the request has finished. I would have the HttpModule register the session in the HttpContext.Items collection.
In your IoC container, you could register something like HttpContextSessionLocator against ISessionLocator.
I should mention that your generic error handling should locate the current session and roll back the transaction automatically, or you could end up committing half a unit of work.

Session Management in Castle Active Record

How do I manage session if I am using Castle Active Record over nHibernate. Basically I can manage the life cycle of ISession on my own if I am using nHibernate directly. But when I am using Castle AR it does not give me a way to manage the life cycle of the session. I want to use single Session per thread.
I am using Castle AR in a WCF service and would like to use Session per WCF Request.
Instead of using ISession, in Castle ActiveRecord you want SessionScope:
using(new SessionScope())
{
; // do work here
}
If you need access to the ISession inside the SessionScope for some reason, you can do this:
ISession dbSession = Castle.ActiveRecord.ActiveRecordMediator
.GetSessionFactoryHolder().CreateSession(
typeof(Castle.ActiveRecord.ActiveRecordBase));
More documentation is here:
http://www.castleproject.org/activerecord/documentation/trunk/usersguide/scopes.html#sess_scope
and here:
http://www.castleproject.org/activerecord/documentation/trunk/manual/scopes.html
I assume you are working in a web app. Is that not the case?
There are a couple of ways to do it - Castle AR documentation
The simplest way is to the use SessionScopeWebModule to give a session per request.

NHibernate many to many and ISession.Close()

I am using NHibernate for my project. i am quite a beginner at working on NHibernate.
I use many-to-many relation mapping "users" and "roles". Here is the code to get the user:
public User GetUser(int userId){
using(ISessuib session = new SessionManager().GetSession())
{
return session.Get<User>(userId);
}
}
public void LazyLoadUsingSessionTest(){
var user= GetUser(1);
Assert.NotNull(user.Roels);
}
it throws an exception:failed to lazily initialize a collection, no session or session was closed
if i do not use the "using" statement in the "GetUser" method,it works. But i must call the session.Close() to release the resource
when i use it in a web page,i only want to use the GetUser(), not the ISession object.so my question is : Does it mean that i must have a ISession object(to release resouse) in my web page? or any better solution?(because i do not want the ISession object appears in my aspx.cs files)
thanks!
You need to use the Session per Request pattern. See this link for an explanation of the best practices for using NHibernate with ASPX.
The simplest way is to use NHibernateUtil.Initialize (read here for details):
using(ISession session = new SessionManager().GetSession())
{
User user = session.Get<User>(userId);
NHibernateUtil.Initialize(user.Roles);
return user;
}
However, sooner or later you would need to somehow manage the sessions in your application. I recommend creating a data provider layer that would give you access to the database. The data provider layer will manage the creation and destruction of sessions. You could either have a session per request or per conversation (single ISession for the duration of an ASP.Net session).
The Summer Of NHibernate video series would be helpful. Session 5 and 13 are most relevant for you.

nhibernate and sessions, please clarify

I am building a web application, and whenever I make a database call I need a session.
I understand creating a session object is very expensive.
I am following the repository pattern here: http://web.archive.org/web/20110503184234/http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/10/08/the-repository-pattern.aspx
He uses something called a UnitOfWork to get the session.
For a web application, shouldn't I be storing the Session in Request.Items collection? So its only created once per request?
Do I really need UofW?
The session IS the unit of work - its basically used to store changes until you flush them to the db. Save a static session factory at startup, and use that to create one session per web request - Request.Items seems a valid place to put the session.
The repository pattern is a wrapper over the unit of work. The repository pattern differs from the UoW pattern in that repo.Save(obj) should save the obj to the db straight away, while the UoW waits for a flush.
My advice would be to skip the repository pattern and use the ISession directly (see http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx)
In the case of NHibernate the key class is the SessionFactory, which SessionProvider is taking care of for you (if you implement it like that). Keep the SessionFactory alive, and it handles the sessions for you.
I've also seem people save the SessionFactory in their IoC.
Use this to manage your sessions:
HybridSessionBuilder
It manages and gives you access to a single session that's used across the entire application.