WEB nhibernate session with asp.net mvc

Discussion in 'OT Technology' started by jdog12, Jan 3, 2009.

  1. jdog12

    jdog12 New Member

    Joined:
    Nov 27, 2004
    Messages:
    5,474
    Likes Received:
    0
    Anybody have any tips on handling an nhibernate session with the asp.net mvc?

    I created a class called SessionHandler, implemented IHttpModule and registered it in web.config.
    Code:
    public class SessionHandler : IHttpModule
        {
            //private static readonly string KEY = "NHibernateSession";
    
            public void Init(HttpApplication context)
            {
                context.EndRequest += new EventHandler(context_EndRequest);
                context.BeginRequest += new EventHandler(context_BeginRequest);
            }
    
            public void Dispose()
            {
            }
    
            private void context_BeginRequest(object sender, EventArgs e)
            {
                HttpApplication application = (HttpApplication)sender;
                HttpContext context = application.Context;
    
                context.Items[NHibernateHelper.CurrentSessionKey] = NHibernateHelper.GetCurrentSession();
            }
    
            private void context_EndRequest(object sender, EventArgs e)
            {
                HttpApplication application = (HttpApplication)sender;
                HttpContext context = application.Context;
    
                ISession session = context.Items[NHibernateHelper.CurrentSessionKey] as ISession;
                if (session != null)
                {
                    try
                    {
                        session.Flush();
                        session.Close();
                    }
                    catch { }
                }
    
                context.Items[NHibernateHelper.CurrentSessionKey] = null;
            }
    
            public static ISession CurrentSession
            {
                get
                {
                    HttpContext currentContext = HttpContext.Current;
                    ISession session = currentContext.Items[NHibernateHelper.CurrentSessionKey] as ISession;
    
                    if (session == null)
                    {
                        session = NHibernateHelper.GetCurrentSession();
                        currentContext.Items[NHibernateHelper.CurrentSessionKey] = session;
                    }
    
                    return session;
                }
            }
    
        }
    
    
    I will replace that current session key with the commented out string declared at top of class.


    The biggest problem I can see with this approach is that a session is created and closed every single time an http request is made, even if it does not need access to the database. Are there any other approaches to this? Anyone have any experience with this asp.net mvc?
     
  2. whup

    whup I wish you had children and.. so that I could step

    Joined:
    Feb 12, 2007
    Messages:
    1,603
    Likes Received:
    0
    Session per request is a good practice, especially if you're going to be using lazy loading, and it's good for performance as it can cut down on the number of database hits per request too.

    I'm sure I read somewhere there's not too much overhead in opening a session so you don't have to worry about that so much.

    Still, you should actually make sure that requests for static content aren't hitting the http modules (e.g. using a static content server or virtual directory).

    You don't have to make it a module either, you can do that in the global application code.
     
  3. whup

    whup I wish you had children and.. so that I could step

    Joined:
    Feb 12, 2007
    Messages:
    1,603
    Likes Received:
    0
    Oh yeah, I hope you're going to change:

    Code:
     try
    {
        session.Flush();
        session.Close();
    }
    catch { }
    
    I'd remove that try/catch in development, and for prod, make sure you log an exception when disposing the session that alerts you somehow so it doesn't fail silently, or it might bite you in the ass later.
     
  4. jdog12

    jdog12 New Member

    Joined:
    Nov 27, 2004
    Messages:
    5,474
    Likes Received:
    0
    Didn't think about doing it in global.asax file, so I did a little google searching and found this. http://pwigle.wordpress.com/2008/11/21/nhibernate-session-handling-in-aspnet-the-easy-way/

    Is there any real advantage to doing it in global.asax file as opposed to doing it in an httpmodule? I like the virtual directory/static content server idea though, thanks.

    Do you have any experience with other ORMs? I started playing around with Subsonic and thought it had some pretty cool features, but I've yet to dive deep in to it. NHibernate is the only one I've used in the past and I'm trying to get away from using Linq to sql and other Microsoft stuff. I'm currently deciding between Subsonic and NHibernate right now. Any input on that?
     
    Last edited: Jan 5, 2009
  5. SLED

    SLED build an idiot proof device and someone else will

    Joined:
    Sep 20, 2001
    Messages:
    28,118
    Likes Received:
    0
    Location:
    AZ, like a bauce!
    I don't have any experience with Subsonic specifically, but NHibernate is well tested in the industry and well known to be a work horse in production apps.

    If you like the Active Record ORM pattern, then take a look at Castle's framework which sits on top of NHibernate. http://www.castleproject.org/activerecord/index.html
     
  6. SLED

    SLED build an idiot proof device and someone else will

    Joined:
    Sep 20, 2001
    Messages:
    28,118
    Likes Received:
    0
    Location:
    AZ, like a bauce!
    Oh, and I wouldn't worry too much about nuking up connections on every request. ADO.Net uses connection pooling which cuts down on the time the framework needs to initialize and tear down connections on every db request.
     
  7. whup

    whup I wish you had children and.. so that I could step

    Joined:
    Feb 12, 2007
    Messages:
    1,603
    Likes Received:
    0
    The advantage to having it in Global.asax is that it's more relevant to the application requests so it makes sense to be in there. There's no real need to separate it out into a separate module, like it would be if it was a dynamic image generation module.

    I use ActiveRecord (which SLED linked to), which is actually just an abstraction layer on top of NHibernate, so instead of writing XML configuration, you simply mark up your entities with attributes.

    AR session per request docs are here: http://using.castleproject.org/display/AR/Enable+Session+per+Request

    I haven't looked much at Subsonic except when investigating things like migrations, so I can't offer any input on that.

    NHibernate has been around for years now and has a big community. Using AR on top of that eases away from any configuration, but you always have the power to go down and do things the NHibernate way too.

    There is NHibernate.Linq (and ActiveRecord Linq) now also but I haven't had a chance to look at them yet.

    With NHibernate/ActiveRecord you also have the option of NHibernate.Search (using Lucene.Net) for powerful full-text searching that keeps the index automatically updated when you update your entities.

    I've definitely found a sweet spot with ActiveRecord over NHibernate and NHibernate.Search, and I'll eventually be looking at addressing things like migrations myself as there's no killer solution for that yet.
     
  8. jdog12

    jdog12 New Member

    Joined:
    Nov 27, 2004
    Messages:
    5,474
    Likes Received:
    0
    I've actually been looking in to the Active Record pattern a little bit. Subsonic seems to do it as it adds FetchAll, FetchByID, etc as static methods and then for every object instance of that class has methods like Save.

    I agree that the attributes are more convenient than the xml files, but can't you use nhibernate mapping attributes to do so?

    Is it that much more convinient?
     
  9. jdog12

    jdog12 New Member

    Joined:
    Nov 27, 2004
    Messages:
    5,474
    Likes Received:
    0
    Also, thanks whup, Session handling was going to be one of my questions about ActiveRecord.
     
  10. whup

    whup I wish you had children and.. so that I could step

    Joined:
    Feb 12, 2007
    Messages:
    1,603
    Likes Received:
    0
    Only you can be the judge of that really.

    I prefer marking up my model with attributes, so AR fits into that nicely.
     
  11. whup

    whup I wish you had children and.. so that I could step

    Joined:
    Feb 12, 2007
    Messages:
    1,603
    Likes Received:
    0
    Oh and I don't like using the aspect of the pattern where you have .Save(), .Find(), .FindAll() methods on the class. I don't extend from ActiveRecordBase (you don't need to) so my classes are clean and lean and there's no object hierarchy.

    I use the Repository pattern for loading/saving/updating entities.

    It makes things easier to test, keeps your model classes clean, and separates concerns.
     
  12. jdog12

    jdog12 New Member

    Joined:
    Nov 27, 2004
    Messages:
    5,474
    Likes Received:
    0
    thanks, I'll do some more research in to it and if I like what I see I might mess around with it.
     

Share This Page