NHibernate和仓储模式

22

Nhibernate+Repository模式应该采用哪种推荐方法?

关于这个问题,有很多不同的文章和意见,我不确定应该选择哪个路径。例如,这篇冗长的文章提供了Query对象的示例,但每个具体的Repository在其构造函数中都接受一个ISession。我在业务层(BL)中应该关心NH sessions吗?

  1. 创建一堆具有一堆特定方法的repositories?
    显然,这太麻烦了,因为BL现在“允许”认识NHibernate(Repository是新的Singleton)。

  2. 创建单一的通用repository,但公开IQueriable<T>并在BL中使用LINQ
    时不时会有一些查询,LINQ-to-NHibernate无法处理(或者我需要手动调整SQL,一百次查询中只需一次)。这很容易通过自定义repo方法实现,但对于依赖LINQ的代码来说几乎不可能。而只是因为LINQ在某些情况下失效而同时使用两者是毫无意义的。

  3. Query对象?
    QueryOver也是NH特有的,这意味着BL再次认识了DAL的实现。

  4. 其他方法?

显然,我需要在某个地方管理事务,也许可以使用Unit-of-work模式(虽然也有很多不同的实现)。


你是在说 DDD 中的仓储库吗? - mathieu
@mathieu:是的。(我不确定我还能想到哪些其他存储库。)但更普遍地说,我正在寻找一种推荐的方式来组织一个使用现代工具和模式编写的2011年应用程序。我以前以多种方式使用过NHibernate,但我讨厌当我需要在我的BL中引用NH特定类时。而且似乎越来越普遍的说法是NH不需要抽象化。 - doe
@doe - 你的 NH 特定类肯定就是你的领域实体吧?否则,你将面临相当大量的属性重复和映射。 - David Neale
是的 - 现在越来越普遍地说,NH不需要抽象,因为我不知道有任何成功完成的体面项目。总会有泄露依赖项。坦率地说 - 我认为好处并不相加。BL(我倾向于使用任务或应用程序层概念)可以了解NH。它通常应该尽可能地隐藏在表示层中。 - David Neale
@david:我所指的NH特定类是指像ICriteria这样的东西,以及严格与数据访问相关的类。不是实体。如果我抱怨在BL中引用实体,那就没有多大意义了,对吧? :) - doe
啊,抱歉我误解了 - 是的,我明白为什么你不想让它们在那里。然而,值得思考的是为什么你不想要它。 - David Neale
2个回答

13

在软件架构领域中有许多互相矛盾的观点,其中许多观点是非常有根据的。

1) 是的,为每个聚合根定义一个仓储可能过度设计,但您可能会发现为该根检索数据的方式可能特定于它,并且您希望能够在自定义存储库中对其进行控制。Ayende的文章阐述得非常清楚,并深刻地反映了典型开发人员“过度设计”解决方案的愿望-往往会损害功能。

2) 使用LINQ与NHibernate是一种选择,但我要强调,如果这样做,必须给自己留下使用条件查询或HQL的回退能力。在那时,您可能会发现自己加入了如此多的异常,以至于会想知道抽象的初始点是什么。

3) QueryOver是对条件查询的类型安全包装器,这使它们对我来说更具吸引力。我经常发现自己回到标准查询,因为它们提供的控制效果 - 备选方案通常是我必须使用“魔法字符串”。这将使NHibernate成为您的数据访问抽象。实际上,它将是比大多数“存储库”更好的抽象,因为它们只提供CRUD方法... 存储库应能够处理查询规范(正如QueryOver的工作方式)。

至于事务-这取决于您的框架。实际上,我认为在应用程序中使用工作单元模式并从其中隐藏实现不切实际或有益(您可以进行抽象化-但这有何意义?-你真的会改变你的ORM吗?)

如果您正在使用ASP.NET,则至少在请求开始时启动事务,在异常中回滚并在结束时提交。

如果您正在使用WinForms,则可能需要考虑每个UI任务的寿命作为您的工作单元。


在评论时,您有1337枚奖牌 :) 6,907 s13 b37 我不敢+1,因为它可能会破坏效果。 - Shagglez

2
这段话的意思是:“这个网站现在似乎无法访问,但我非常喜欢Bob Craven的方法,并且已经在一些大型项目中使用过它:他使用泛型和UOW模式进行数据访问。”其中,......是超链接。
是的,当你需要回到SQL时,这可能有点麻烦,但我使用了一个数据服务层来抽象它。也就是说,数据服务层在可能的情况下(90%的时间)使用通用的DAO,而在其他地方使用原始的SQL/其他框架。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接