我在晚上的其余时间阅读了StackOverflow的问题以及一些关于该主题的博客文章和链接。他们都变得非常有帮助,但我仍然觉得他们并没有真正回答我的问题。静态存储库是使用NHibernate的正确方法吗?
所以,我正在开发一个简单的Web应用程序。我想创建一个可重用的数据访问层,以后我可以在其他解决方案中重用。其中99%是网络应用程序。这似乎是我学习NHibernate及其周围模式的一个很好的借口。
我的目标如下:
- 我不想业务逻辑层了解数据库的内部运作任何东西,也没有NHibernate的本身。
- 我希望业务逻辑层尽可能少地假设数据访问层。
- 我希望数据访问层尽可能简单和易于使用。这将是一个简单的项目,所以我不想过分复杂。
- 我希望数据访问层尽可能地不侵入。
会不会考虑到所有这些,我决定采用流行的仓库模式。我在本网站和各种开发人员博客上阅读了这个主题,并且听到了有关工作单元模式的一些内容。
我也环顾四周,检查出各种实现。 (包括FubuMVC contrib和SharpArchitecture,以及某些博客上的内容)。我发现其中大多数操作原理相同:它们创建一个“工作单元”,在存储库实例化时它们实例化,它们开始一个事务,做东西,然后提交,然后重新开始。所以,只有一个ISession
每Repository
就是这样。然后,客户端代码需要实例化一个存储库,做一些事情,然后处理。
此使用模式不符合我需要的是尽可能的简单化,所以我开始思考别的东西。
我发现NHibernate的已经拥有的东西,这使得“工作单位”不必要实现自定义,那就是CurrentSessionContext
类。如果我正确配置会话上下文,并在必要时进行清理,那么我很好。
所以,我想出了这个:
我有一个名为NHibernateHelper
内部静态类。首先,它有一个名为CurrentSessionFactory
的静态属性,它在第一次调用时实例化会话工厂并将其存储在静态字段中。 (每一个ISessionFactory
一个AppDomain
是不够好。)然后,更重要的是,它有一个CurrentSession
静态属性,检查是否有绑定到当前的会话上下文的ISession
,如果没有,创建一个,并结合它,它返回ISession
绑定到当前会话上下文。
因为它将被WebSessionContext
大多使用(每HttpRequest
所以,一个ISession
,尽管对于单元测试,我配置ThreadStaticSessionContext
),它应该无缝地工作。创建并绑定ISession
后,它将事件处理程序挂接到HttpContext.Current.ApplicationInstance.EndRequest
事件,该请求在请求结束后负责清理ISession
。(当然,只有做到这一点,如果它真的是在网络环境中运行。)
所以,这一切成立,NHibernateHelper
随时都可以返回一个有效的ISession
,所以没有需要实例一个为“工作单元”正确运行的Repository实例。相反,Repository
是一个静态类,它与NHibernateHelper.CurrentSession
属性中的ISession
一起运行,并通过泛型方法公开功能。
所以,基本上,我结束了两个非常懒惰的单身人士。
我很好奇,你怎么看待这个问题? 这是一种有效的思维方式,还是我完全偏离了这里?
编辑:
我必须指出的是,NHibernateHelper类是内部的,所以几乎看不到消费者的存储库。
另一个想法是,为了引入依赖注入到解决方案中,需要创建一个名为IDataProvider
的接口,并在第一次调用Repository
类时实例化该接口的一个实例。 (然而,实现代码应能照顾上下文的概念也。)
编辑2:
似乎很多人都喜欢我的想法,但仍有关于它的太少意见答案。
我可以假设这是一个正确的方式来使用NHibernate,然后呢? :P
嗯是的,但我认为我的解决方案有一个更容易使用的语法,并且在对象实例化方面以及内存使用方面肯定更少。 – Venemo 2010-04-26 22:45:54