I was having a problem with session management revolving around lazy loading and cascades. i was bouncing back and forth between two bugs: either close the session after getting the entity, which means I can't lazy load, or keep the session open, but have problems cascading deletes.
I had:
Code:
public T Get(int id)
{
return GetsANewSession().Get<T>(id);
}
public void Delete(T entity)
{
GetsANewSession().Delete(entity);
}
which meant that my Group.Printers was opened under the session requested for in Get, but when I try to delete it, I get a new session - which doesn't jive with NHibernate.
I know a common (ASP.NET) model is to open a single session at the start of a request and close it at the end. This ensures lazy-loading can work as-intended and that deletes against entities occurs on the same session they are associated with. I don't particularly like that model (in no small part because the default behavior of sessions is to close whenever a transaction is committed, and yes, I know that can be overwritten).
My approach is to keep a dictionary (per request) of the association between entities and their sessions, and use that session when doing anything else with that entity for the request).
It appears to work fine, but I wanted to see if anyone had any insight to give.
Here's roughly what I have:
Code:
public virtual T Get(int id)
{
var session = GetsANewSession();
var entity = session.Get<T>(id);
AssociateSessionWithObject(entity, session);
return entity;
}
public void Delete(T entity)
{
GetSmartSession(entity).Delete(entity);
}
private void AssociateSessionWithObject(T entity, ISession session)
{
_association[entity, session];
}
private ISession GetSmartSession(T entity)
{
return (_association.ContanisKey(entity)) ? _association[entity] : CreateANewSession();
}
Everything is largely low-level pseudo-code, just trust that _association is thread-specific. I was kinda surprise that I NHibernate didn't provide this kinda functionality (something like NHibernateUtil.GetSession(entity)) - and when I didn't see that I figured this might be a totally incorrect approach.