如何使用WebAPI / NHibernate实现Session Per Conversation模式

时间:2014-02-24 03:55:53

标签: c# asp.net-mvc nhibernate dependency-injection asp.net-web-api

我有一个MVC项目,我专门使用自定义的“工作单元”模式,在后端使用NHibernate,我将其作为IUnitOfWorkIUnitOfWorkFactory接口暴露给我的应用程序;这些接口通过Ninject作为我的NHibernate实现注入。

我在修改后的“每个请求的会话”样式中使用我的UOW ...当我需要执行数据库操作时,我从注入的IUnitOfWork显式生成IUnitOfWorkFactory;将CRUD保持在它所属的位置(在我的视图和控制器之外)并且有效地防止意外的N + 1编码问题似乎要容易得多。当然,实施起来有点困难,但到目前为止,我对此非常满意。

现在我想实现一个呈现IQueryable<Entity>式REST调用的WebAPI,而我的UOW模式并没有挖掘它。 Queryables总是爆炸,试图调用NHIBnate会话。

我在线阅读了一些有关如何实现DelegatingHandler来管理WebAPI调用会话的内容......但我发现了几个问题:

  1. 似乎所有的例子都假设了一个“每个请求的会话”模式......这是迄今为止最流行的模式,但不是我正在使用的模式,所以我不确定这是不是正确的方向去。
  2. 目前尚不清楚如何为这些Web API调用专门实现此处理程序。
  3. 我看到很多建议使用“每次会话会话”模式,这种模式可能比“每个请求的会话”模式更长寿......听起来它可能适合这种努力,但是如何实现它的文档有点稀疏。
  4. 我见过的所有示例实现都将NHibernate ISession与Web应用程序紧密结合,使用内置的NHibernate机制(CurrentSessionContext.Bind(ISession));我更愿意引用我的IUnitOfWork接口,并相信它可以维护它所需的会话。
  5. 所以我的问题是,如何使用我自己的IQueryable<Entity>接口实现一个IUnitOfWork RESTful API,以防止松散耦合的NHibernate后端?

1 个答案:

答案 0 :(得分:1)

对于简单的每请求会话实现,您将面临同样的问题。例如:

// GET api/companies
public IQueryable<Company> GetCompanies()
{
    return _session.Query<Company>();
}

我通常在事务中包装所有数据库操作,包括选择,但由于查询执行被延迟,我不能在此方法中执行此操作。可以通过创建ActionFilter并覆盖OnActionExecuted来实现,但难点是在过滤器中获得对ISession或IUnitOfWork实现的引用。有一些例子说明了如何使用网络上的Ninject和其他依赖注入框架来实现这一目标。

就个人而言,我没有看到抽象ISession的价值,特别是在Web API中,拥有一个没有执行数据库操作的资源是非常罕见的。每次会话的会话绝对不是一个很好的模式;它通常是指通过多次服务器往返保持会话开放。

我首选的架构是使用Ninject来管理ISessionFactory和ISession生命周期(分别为singleton和per-request)并将ISession注入Api控制器。但您也可以将其注入存储库或工作单元实现。