我开始构建一个应用程序,我打算使用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框架),最佳实践是什么?
提前致谢
答案 0 :(得分: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
以上所有内容都是每个请求的会话变体。所有事情的共同点是不必手动担心创建会话/事务。他们将自动提交/回滚事务。
答案 1 :(得分: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();
}
}
答案 2 :(得分: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);
}
}