NHibernate Sessions with ASP.NET
January 30th, 2008
I've been working with NHibernate and ASP.NET and I've found quite some troubles to get NHibernate to work the way I wanted. We have an abstraction layer on top of NHibernate that hides the NHibernate intrinsics. With this abstraction layer we handle all the persistance for the domain entities.
The problem comes with the NHibernate session handling. We open a session per request (if needed) and we may store some entities in ASP.NET Session, Cache or Application. Basically, the problems present them selfs when we obtain an object with some NHibernate session, and later on we try to handle that object after the owning session has been closed. Example: put some object in Cache and try to access some collections later on.
Changing the current NHibernate session for an object proved to be quite troublesome (or... I really missed the best way to do it). We detected two scenarios where we needed to update the session for an NHibernate mapped class:
- When we had an NHibernate proxy with a closed session
- When we had the object, with some uninitialized NHibernate bags/sets/whatever - in this case we can work with the object, but we'll get an error when we try to access an uninitialized collection
These two scenarios will present the calling code with the following exception: Could not initialize proxy - the owning Session was closed.
I really, really searched the web to find some answers, but I got nothing. The NHibernate documentation suggests the use NHibernateUtil.Initialize to handle this problem, but this method assumes that the session's still available - and that may not be true.
To update the NHibernate proxy's session, we perform the following:
-
void CheckProxySession(object entity, ISession target)
-
{
-
INHibernateProxy proxy = entity as INHibernateProxy;
-
if (proxy == null) {
-
return;
-
}
-
if (!NHibernateUtil.IsInitialized(proxy)) {
-
LazyInitializer initializer = NHibernateProxyHelper.GetLazyInitializer(proxy);
-
initializer.Session = target.GetSessionImplementation();
-
initializer.Initialize();
-
}
-
}
To update an object that's not a proxy and that have some uninitialized NHibernate containers:
-
void CheckObjectSession(Loki.DataRepresentation.IEntity entity)
-
{
-
ISession session = null;
-
try {
-
-
session = GetSession();
-
-
// hack to force NHibernate to associate the new session with the given entity
-
session.Update(entity);
-
-
} catch {
-
if (session != null) {
-
session.Dispose();
-
}
-
throw;
-
}
-
}
This will solve the lazy initialization issue, but it may bring some extra problems if you change the objects and don't update/flush. You may get an NHibernate exception if you try to associate a dirty object to a new session, or you may get some troubles with transaction related logic.
Does anyone know a better solution to this problem?
Related Posts
- Domain-specific programming languages
- Best way to load XML configuration
- Hierarchical roles in ASP.NET
- Generics limitation or flaw?
- Orion's Belt AI




January 30th, 2008 at 11:17 pm
Can’t you hold the NHibernate session open during all the HTTP request lifetime?
Check the Open Session in View pattern: http://www.hibernate.org/43.html
January 30th, 2008 at 11:22 pm
Yes I can… that’s what I do. The problem comes when you try to use the object in a different request… have you really read the post?
January 31st, 2008 at 9:31 am
this should be taken care by your container. jboss deals with this by means of transactions. a section is opened when a business call is created, and is destroyed as soon as the business call is closed. a transaction is closed too
January 31st, 2008 at 4:14 pm
I must have missed the 2nd paragraph! :p
I never did cache by myself with NHibernate, I’ve used a second-level NHibernate cache, that shares data between sessions (as long as sessions were created by the same SessionFactory). This could be used with ASP.NET cache or other cache providers and seems to make caches/session management transparent to the programmer.
Have I missed your point again? :p
Probably yes… I’m not any NHibernate expert.
February 1st, 2008 at 1:43 pm
To associate a disconnected object (entity) to a new session I believe you need to call session.Lock() passing in the object that you want to associate with the session. For example:
CurrentSession.Lock(yourEntity, LockMode.None);
February 15th, 2008 at 9:12 am
Hi!
I used to have problems with the session handling as well, but now I’m using Spring.Net’s HibernateTemplate and OSIV so it’s no problem for me anymore. Also there is tons of posts on Spring.Net’s user forum regarding these problems, take a look at:http://forum.springframework.net/forumdisplay.php?f=15
Whenever I have a detached object and want to attach it to a new session (e.g when it comes back to the server), I simply use: session.Lock(entity, LockMode.Read); This is how the NHibernate documentation recommends reattachment if you haven’t modified the entity. If you have modified it, then session.update will reattach the entity and synchronize the changes into the new session. When you flush the session these changes will go into the DB.
Take a look at the Spring.Net NHibernate forum, there is a lot of discussions, tips and recommendations on how to solve these common issues.
Cheers,
Steinar.
May 12th, 2008 at 5:11 pm
Thank you, I’ve been battling with this for some time, and it’s hard to find the right thing to search for in Google.
July 17th, 2008 at 8:57 am
[...] code is very slow. Some time ago, I had to go into NHibernate source code to understand how I could use sessions with ASP.NET, and I noticed that NHibernate uses a lot of internal objects. Well, on this case, I am fetching a [...]
December 17th, 2008 at 10:35 am
i have the same difficult
originaly my code was:
Dim iSession As ISession = ConfigLoader.GetInstance.session
Try : return iSession.Load(GetType(DataModel.clsContact), Id)
Catch ex As Exception : Throw New clsException(ex)
Finally : iSession.Disconnect()
End Try
but after testing, i discover that session use proxy for assignation. so if session was disconnected, proxy isnot aviable.
we can turn around this difficult by instanciate a new object inside the session and return it like that:
Dim iSession As ISession = ConfigLoader.GetInstance.session
Try
Dim obj As clsContact = iSession.Load(GetType(DataModel.clsContact), Id)
Return obj ‘ceci est absolument nécessaire car l’objet n’est réellement instancié qu’au moment de l’assignation. or un return de l’objet = instanciation dans la couche suppérieur = isession déconnectée => plantage…
Catch ex As Exception : Throw New clsException(ex)
Finally : iSession.Disconnect()
End Try
January 26th, 2009 at 7:52 pm
[...] ASP.NET MVC application NHibernate Session Module opens unecessary transactions for CSS and images NHibernate Sessions with ASP.NET Posted by serge desmedt Filed in .NET, Software Design Tags: ASP.NET, [...]
March 26th, 2009 at 7:04 pm
I’m kind of new to NHibernate and was wondering if someone could shed some light on the behavior that I’m experiencing as well as a possible solution.
I have an NHibernate entity called User which upon login of my ASP.NET app, if valid, i retrieve and store in asp.net session. If null, I throw them back to the login page, etc…
Well, on this User object there are some other associations that I want to traverse later on subsequent http requests but I get the exception as the proxy’s are no longer associated with the active session.
(example: accessing User.UserCompanies[0].Company.Name will cause LazyInitializationException with no session associated)
What is the best way to make these proxy’s “alive” again without forcing them to actually initialize? I’m using the Session-Per-Request pattern. I’d prefer not having to re-get the User based on ID each request but am open to the most efficient solution.