我有一个MVC项目,我专门使用自定义的“工作单元”模式,在后端使用NHibernate,我将其作为IUnitOfWork
和IUnitOfWorkFactory
接口暴露给我的应用程序;这些接口通过Ninject作为我的NHibernate实现注入。
我在修改后的“每个请求的会话”样式中使用我的UOW ...当我需要执行数据库操作时,我从注入的IUnitOfWork
显式生成IUnitOfWorkFactory
;将CRUD保持在它所属的位置(在我的视图和控制器之外)并且有效地防止意外的N + 1编码问题似乎要容易得多。当然,实施起来有点困难,但到目前为止,我对此非常满意。
现在我想实现一个呈现IQueryable<Entity>
式REST调用的WebAPI,而我的UOW模式并没有挖掘它。 Queryables总是爆炸,试图调用NHIBnate会话。
我在线阅读了一些有关如何实现DelegatingHandler
来管理WebAPI调用会话的内容......但我发现了几个问题:
ISession
与Web应用程序紧密结合,使用内置的NHibernate机制(CurrentSessionContext.Bind(ISession)
);我更愿意引用我的IUnitOfWork
接口,并相信它可以维护它所需的会话。所以我的问题是,如何使用我自己的IQueryable<Entity>
接口实现一个IUnitOfWork
RESTful API,以防止松散耦合的NHibernate后端?
答案 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控制器。但您也可以将其注入存储库或工作单元实现。