Reputation: 26782
I'm learning NHibernate and was looking at some code recently where NHibernate was used in an ASP.Net MVC project.
In a certain part of this app, entities loaded from NH are being kept in the (HttpContext) Session. Is this OK, or are there any dangers with this if you use (NHibernate) Session-per-request pattern?
Upvotes: 1
Views: 1551
Reputation: 26909
Yes you can and it does make sense to cache a frequently used object if you are fetching it based on a property that is not the primary key.
My site has a Person class which represents a specific user on the site. On any given web request I need to fetch the current logged-in user object several times to access various configuration settings and properties that are specific to the current user. Rather than hitting the database every time, I store the current user in HttpContext.Items[] and I have a static method that checks if the Items cache contains the current user. If it does, return it, if it doesn't get it from the database and add it to the cache so its available next time:
public static Person CurrentUser
{
get
{
if(!IsAuthenticated) return null;
Person person = (Person) HttpContext.Current.Items[HttpContext.Current.User.Identity.Name];
if(person != null) return person;
IPersonDao personDao = new PersonDao();
person = personDao.getByUsernameEmail(HttpContext.Current.User.Identity.Name);
if(person==null)
{
FormsAuthentication.SignOut();
HttpContext.Current.Response.Redirect("/");
}
HttpContext.Current.Items[HttpContext.Current.User.Identity.Name] = person;
return person;
}
}
I also store my NHibernate session object in HttpContext.Items so the session and the cached object will be garbage collected at the same time at the end of the HttpRequest, what you don't want is for the object to survive past the lifetime of the session, otherwise a new session may start and NHibernate will barf with a NHibernate.NonUniqueObjectException because the object is bound to another session.
Its worth pointing out that the NHibernate's 1st level cache keeps all objects accessed by the session cached by ID. If I was calling session.get(id) there is no need to cache as NHibernate's 1st level cache maintains objects by their id. But in the above case where I am fetching the person object by the User.Identity.Name the 1st level cache doesn't work as the user's username is not the primary key of the object.
More info on HttpContext.Items https://web.archive.org/web/20210608183011/http://aspnet.4guysfromrolla.com/articles/060904-1.aspx
DO NOT use HttpContext.Cache, which for some reason lasts beyond the Http Request.
Upvotes: 0
Reputation: 8381
"Session per request" with NHibernate does not have a relationship with HttpSession. "Session" in session per request is the NHibernate ISession. It's safe to store NHibernate.ISession in HttpContext.Current.Items at the beginning of the request and dispose it at the end of the request.
Upvotes: 0
Reputation: 99750
I wouldn't recommend it unless you really know what you're doing. Off the top of my head:
If you want to have cross-request conversations check out NHibernate.Burrow which is a framework designed for this specific purpose.
Upvotes: 3