使用NHibernate和Spring.Net实现存储库
我想要抓住NHibernate,流利NHibernate和Spring。使用NHibernate和Spring.Net实现存储库
继领域驱动设计的校长,我写组成的标准分层的Web应用程序:
- 一个表现层(ASP.Net)
- 业务层,包括:
- 一个应用程序层(基本上,一组方法对UI层可见)
- 存储库接口和域组件(由应用程序层使用)
- 持久层
我想帮助确定以这样一种方式实例化的NHibernate的ISession的方式(基本上在业务层中定义的库接口的实现),它可以由多个共享存储库在对业务层的单个请求的生命周期中。具体来说,我想:
允许ISession实例和任何交易outwith库实现控制
允许ISession的(也许是由IOC框架,一个拦截器的某些方面?) (可能通过注入或通过某些共享的“上下文”抽象)
避免任何不必要的事务被创建(即只有只读操作已被执行时)
让我写使用SQLLite
允许我用流利的NHibernate的
使仓库实现保持无知主机环境的测试。我还不知道businese层是否将在表现层中运行,或者将在WCF(在IIS中)下单独托管,所以我不想将我的代码与HTTP上下文过于紧密地绑定在一起(例如)。
我第一次尝试解决这个问题一直在使用注册表模式;将ISession实例存储在ThreadStatic属性中。然而,后来的阅读表明,这不是最好的解决方案(因为ASP.Net可以在页面生命周期内切换线程,我相信)。
任何想法,部分解决方案,模式名称,指向最新样本(NHibernate 2)的指针都将非常感激地收到。
我还没有使用Spring.NET,所以我不能对此发表评论。然而,其余的听起来很明显(或者不那么显着,我们几乎不是第一个实现这些东西的),这与我自己的经验类似。我也很难找到一个真正的最佳实践,所以我尽可能多地阅读,并提出自己的解释。
在我的情况下,我希望事务/会话管理在存储库的外部以及使存储库的问题不致从其中冒出来(即使用存储库的代码不需要知道它在内部使用NHibernate并且不应该不需要知道关于NHibernate会话管理的任何事情)。在我的情况下,决定默认情况下会创建交易,以免开发人员忘记交易,所以我必须拥有只读转义机制。我使用内部的NHibernate ISession实例存储与工作单元模式。调用代码(我还创建了一个UOW DSL接口)可能看起来像:
using (var uow = UoW.Start().ReadOnly().WithHttpContext()
.InNewScope().WithScopeContext(ScopeContextProvider.For<CRMModel>())
{
// Repository access
}
在实践中,这可能取决于很多方面是如何已经可以尽可能短UoW.Start()
。 HttpContext
部分指的是UoW的存储位置,在这种情况下,不出意外的是HttpContext
。正如您所提到的,对于ASP .NET应用程序,HttpContext
是存储事物最安全的地方。 ScopeContextProvider
基本上确保为UoW(适合的数据库/服务器的ISession实例,其他设置)提供正确的数据上下文。 “ScopeContext”概念也使得插入“测试”范围上下文变得容易。
执行此路由会使存储库明确依赖UoW接口。其实,你可能能够抽象一些,但我不确定我看到了好处。我的意思是,每个存储库方法检索当前的UoW实例,然后抽出ISession对象(或者简单地为那些不使用NHibernate的方法使用SqlConnection)来运行NHibernate查询/操作。这对我很有用,因为它似乎也是确保当前UoW对于可能需要运行CRUD的方法不是只读的理想时间。
总体来说,我认为这是一个办法可以解决所有的点:
- 允许会话管理是外部存储库
- 的Isession上下文可以在上下文提供一个测试嘲笑或尖环境
- 避免了不必要的交易(当然,你必须倒置我做什么,有一个
.Transactional()
来电或东西) - 我不明白为什么你不能使用SQLite测试,因为这更多的NHibernate的关注
- 我用流利的NHibernate的自己
- 允许库无知主机环境(即库调用者控制UOW存储上下文)
对于UOW执行,我部分地在我开始之前踢我自己不要更多地环顾四周。有一个名为machine.uow的项目,据我了解,它相当流行,并且可以很好地与NHibernate配合使用。我没有玩过很多,所以我不能说它是否像我自己写的那样整齐地解决了我的所有需求,但它也可能节省了开发时间。
也许我们会收到一些有关我出错或如何改善事情的评论,但我希望这至少对某些方面有所帮助。
仅供参考,我使用的软件栈:
- ASP。NET MVC
- 功能NHibernate NHibernate的
- Ninject的顶部依赖注入
你所描述由Spring.NET框架支持几乎开箱即用。只有FluentNHibernate,你需要在Spring.NET中添加一个自定义的SessionFactory(不是很多代码,看这里:Using Fluent NHibernate in Spring.NET)。
每个存储库都可以使用相同的ISession,只需在存储库中注入SessionFactory并使用Spring.NET的事务服务即可。
只要试一下,他们有非常全面的文件imho。
关于FluentNhibernate,还有一个开放的jira:http://jira.springframework.org/browse/SPRNET-1232 沙地的其他资源可能是Documentation:http://www.springframework.net/doc- latest/reference/html/nh-quickstart.html 对于IntegrationTesting suppport,请查看http://www.springframework.net/doc-latest/reference/html/testing.html#unit-testing。 – tobsen 2009-12-03 23:07:30