8

I am starting to build an app, and I'm planning to use ServiceStack. Just want to know what are the best practices/good approaches for handling NHibernate ISession or, other "per request" context specific session objects.

I thought registering a ISessionFactory in the Ioc like:

container.Register<ISessionFactory>(sessionFactory);

And when needed get a new Session object... Or maybe provide the session object directly:

container.Register<ISession>(c => sessionFactory.OpenSession()).ReusedWithin(ReuseScope.None);

Or either handle the ISession and a default transaction via the Global.asax BeginRequest event:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    var session = factory.OpenSession();
    ITransaction itrans = session.BeginTransaction();
    Context.Items.Add("session", session);
    Context.Items.Add("trans", itrans);
}

So, I am kind of lost, what are the best practices, given the above technologies, or similar ones, like EF or another Rest-Services framework?

Thanks in advance

RMalke
  • 4,048
  • 29
  • 42

3 Answers3

4

Creating a session per request using a HttpHandler is the most common way of doing it that I have found. Ayende has explained that creating a session is really light weight. http://ayende.com/blog/4123/what-is-the-cost-of-opening-a-session

Ayende actually has series of posts where in he gradually builds out the data access solution. Each post explains why he did what he did and what issues need to be resolved with the steps taken so far. Start here: http://ayende.com/blog/4803/refactoring-toward-frictionless-odorless-code-the-baseline

Finally, http://nhforge.org/blogs/nhibernate/archive/2011/03/03/effective-nhibernate-session-management-for-web-apps.aspx

All of the above are variations of session per request. The common thing across all is not having to manually worry about creating a session/transaction. They will commit/rollback the transactions automatically.

Amith George
  • 5,806
  • 2
  • 35
  • 53
3

See this blog post for a complete example of how to optimally use ServiceStack and NHibernate together:

http://www.philliphaydon.com/2012/06/using-nhibernate-with-servicestack/ Here's the AppHost example used in the above post:

public class Global : HttpApplication
{
    public class SampleServiceAppHost : AppHostBase
    {
        private readonly IContainerAdapter _containerAdapter;
        public SampleServiceAppHost(ISessionFactory sessionFactory)
            : base("Service Stack with Fluent NHibernate Sample", typeof(ProductFindService).Assembly)
        {
            base.Container.Register<ISessionFactory>(sessionFactory);
        }

        public override void Configure(Funq.Container container)
        {
            container.Adapter = _containerAdapter;
        }
    }

    void Application_Start(object sender, EventArgs e)
    {
        var factory = new SessionFactoryManager().CreateSessionFactory();

        (new SampleServiceAppHost(factory)).Init();
    }
}
mythz
  • 141,670
  • 29
  • 246
  • 390
3

I know this is an old question, but I figured I'd go ahead and show anyone who is still interested in an alternate answer how we just did this.

We are using the ServiceRunner in the new ServiceStack API thusly:

public class BaseServiceRunner<TRequest> : ServiceRunner<TRequest>
{
    public BaseServiceRunner(AppHost appHost, ActionContext actionContext)
    : base(appHost, actionContext) { }

    public override void OnBeforeExecute(IRequestContext requestContext, TRequest request)
    {
        var req = request as MyRequestType;

        if(req == null)
            base.OnBeforeExecute(requestContext, request);

        var factory = TryResolve<NHibernate.ISessionFactory>();
        var session = factory.OpenSession();
        var trans = session.BeginTransaction(IsolationLevel.ReadCommitted);

        requestContext.SetItem("session", session);
        requestContext.SetItem("transaction", trans);
    }        

    public override object OnAfterExecute(IRequestContext requestContext, object response)
    {
        var trans = requestContext.GetItem("transaction") as ITransaction;
        if (trans != null && trans.IsActive)
            trans.Commit();

        var session = requestContext.GetItem("session") as ISession;
        if (session != null)
        {
            session.Flush();
            session.Close();
        }

        return base.OnAfterExecute(requestContext, response);
    }

    public override object HandleException(IRequestContext requestContext, TRequest request, Exception ex)
    {
        var req = request as MyRequestType;
        if(req != null)
        {
            var trans = requestContext.GetItem("transaction") as ITransaction;
            if (trans != null && trans.IsActive)
                trans.Rollback();

            var session = requestContext.GetItem("session") as ISession;
            if (session != null)
            {
                session.Flush();
                session.Close();
            }
        }
        return base.HandleException(requestContext, request, ex);
    }        
}   
Eric Morris
  • 155
  • 6
  • 1
    Can you please elaborate on how you used this? The ServiceStack documentation really isn't making sense on how to use these ServiceRunners.. – cjones26 Apr 17 '13 at 05:23
  • I added code to add in your app host. Not sure how to use the Service runner from the service. – Robert Baker Jul 15 '13 at 10:54
  • Just saw the requests for further details, might be too late to be helpful, but maybe someone else wants to know. `code` public class AppHost : AppHostBase { public AppHost() : base("Service", typeof (AccessService).Assembly) { } public override void Configure(Container container) { } public override IServiceRunner CreateServiceRunner(ActionContext actionContext) { return new BaseServiceRunner(this, actionContext); }`code` – Eric Morris Feb 07 '14 at 20:14