【发布时间】:2011-02-12 15:04:01
【问题描述】:
我晚上剩下的时间都在阅读 StackOverflow 问题以及有关该主题的一些博客条目和链接。结果他们都非常有帮助,但我仍然觉得他们并没有真正回答我的问题。
所以,我正在开发一个简单的 Web 应用程序。我想创建一个可重用的数据访问层,以后可以在其他解决方案中重用。其中 99% 将是 Web 应用程序。这似乎是我学习 NHibernate 和它周围的一些模式的一个很好的借口。
我的目标如下:
- 我不想让业务逻辑层知道任何关于数据库内部运作的信息,也不想知道 NHibernate 本身。
- 我希望业务逻辑层对数据访问层有尽可能少的假设。
- 我希望数据访问层尽可能简单易用。这将是一个简单的项目,所以我不想让任何事情变得过于复杂。
- 我希望数据访问层尽可能不具有侵入性。
考虑到这一切,我决定使用流行的存储库模式。我在此站点和各种开发博客上阅读了有关此主题的信息,并且听说了一些有关工作单元模式的内容。
我还环顾四周并检查了各种实现。 (包括 FubuMVC contrib 和 SharpArchitecture 以及一些博客上的东西。)我发现它们中的大多数都遵循相同的原则:它们创建一个“工作单元”,在实例化存储库时实例化,它们启动事务,做事,提交,然后重新开始。所以,每个Repository 只有一个ISession,仅此而已。然后客户端代码需要实例化一个存储库,用它做一些事情,然后释放。
这种使用模式不能满足我尽可能简单化的需求,所以我开始考虑别的东西。
我发现 NHibernate 已经有了一些不需要自定义“工作单元”实现的东西,那就是 CurrentSessionContext 类。如果我正确配置会话上下文,并在必要时进行清理,我就可以开始了。
所以,我想出了这个:
我有一个名为NHibernateHelper 的内部静态类。首先,它有一个名为CurrentSessionFactory 的静态属性,它在第一次调用时会实例化一个会话工厂并将其存储在一个静态字段中。 (每个ISessionFactory 一个AppDomain 就足够了。)然后,更重要的是,它有一个CurrentSession 静态属性,它检查是否有一个ISession 绑定到当前会话上下文,如果没有,则创建一,并绑定它,它返回与绑定到当前会话上下文的ISession。
因为它将主要与WebSessionContext 一起使用(因此,每个HttpRequest 一个ISession,尽管对于单元测试,我配置了ThreadStaticSessionContext),它应该可以无缝工作。在创建和绑定ISession 之后,它会将事件处理程序挂钩到HttpContext.Current.ApplicationInstance.EndRequest 事件,该事件处理程序负责在请求结束后清理ISession。 (当然,只有当它真的在 Web 环境中运行时才会这样做。)
因此,通过所有这些设置,NHibernateHelper 将始终能够返回有效的ISession,因此无需实例化 Repository 实例以使“工作单元”正常运行。相反,Repository 是一个静态类,它使用来自NHibernateHelper.CurrentSession 属性的ISession 进行操作,并通过泛型方法通过它公开功能。
所以,基本上,我最终得到了两个非常懒惰的单身人士。
我很好奇,您对此有何看法? 这是一种有效的思维方式,还是我完全偏离了轨道?
编辑:
我必须指出 NHibernateHelper 类是内部的,对存储库的消费者来说几乎是不可见的。
另一个想法是,为了在解决方案中引入依赖注入,创建一个名为IDataProvider 的接口,并在第一次调用Repository 类时实例化该接口的一个实例。 (但是,实现代码也应该能够处理上下文的概念。)
编辑 2:
似乎很多人喜欢我的想法,但答案中关于它的意见仍然太少。
我可以假设这是使用 NHibernate 的正确方法吗? :P
【问题讨论】:
标签: .net asp.net nhibernate orm repository-pattern