8

我开始构建一个应用程序,我打算使用 ServiceStack。只想知道处理 NHibernate ISession 或其他“每个请求”上下文特定会话对象的最佳实践/好方法是什么。

我想在 Ioc 中注册一个 ISessionFactory 就像:

container.Register<ISessionFactory>(sessionFactory);

并在需要时获取一个新的 Session 对象......或者直接提供会话对象:

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

或者通过 Global.asax BeginRequest 事件处理 ISession 和默认事务:

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);
}

所以,我有点迷茫,鉴于上述技术或类似技术,如 EF 或其他 Rest-Services 框架,最佳实践是什么?

提前致谢

4

3 回答 3

4

使用 HttpHandler 为每个请求创建一个会话是我发现的最常见的方法。Ayende 解释说创建会话真的很轻量级。http://ayende.com/blog/4123/what-is-the-cost-of-opening-a-session

Ayende 实际上有一系列帖子,其中他逐渐构建了数据访问解决方案。每篇文章都解释了他为什么做了他所做的事情,以及到目前为止所采取的步骤需要解决哪些问题。从这里开始:http: //ayende.com/blog/4803/refactoring-toward-frictionless-odorless-code-the-baseline

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

以上所有内容都是每个请求的会话变体。所有人的共同点是不必手动担心创建会话/事务。他们将自动提交/回滚事务。

于 2012-07-06T04:08:32.683 回答
3

我知道这是一个老问题,但我想我会继续向任何对替代答案感兴趣的人展示我们是如何做到这一点的。

因此,我们在新的 ServiceStack API 中使用了 ServiceRunner:

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);
    }        
}   
于 2013-03-20T20:50:47.153 回答
3

有关如何以最佳方式同时使用 ServiceStack 和 NHibernate 的完整示例,请参阅此博客文章:

http://www.philliphaydon.com/2012/06/using-nhibernate-with-servicestack/ 这是上面帖子中使用的 AppHost 示例:

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();
    }
}
于 2012-07-06T03:55:38.243 回答