nHibernate,一个 n 层解决方案 + 请求咨询
Posted
技术标签:
【中文标题】nHibernate,一个 n 层解决方案 + 请求咨询【英文标题】:nHibernate, an n-Tier solution + request for advice 【发布时间】:2010-10-20 16:24:42 【问题描述】:我有机会开发一个稍微复杂的项目,并且一直在研究我可以用来解决这个项目的各种方法。通常我会使用传统的 3 层方法,但在花了一些时间查看各种选项之后,我有一个预感,某种 ORM 可能更合适,我正在考虑使用 nHibernate。但是,我正在寻找有关实施 nHibernate 的一些指导,更具体地说,我将如何构建我的 BL 和 DAL 与 nHibernate。
使用 nHibernate,我将创建我的对象(或 DTO?)并在我的 DAL 中使用 nHibernate 方法进行我的 CRUD 交互。但我无法理解的是,在 DAL 中定义的对象可能会更好地位于 BL 中,即可以轻松执行验证和其他内容的地方,我只使用来自各种 ObjectFactory/ObjectRepositories 的 DAL .不幸的是,我读过的许多文章似乎都没有提到或绕过这一点,我有点困惑。
在 3 层系统中使用 nHibernate 时,更容易接受或更容易的实施方法是什么?或者,从数据层到表现层通过业务层暴露对象的常规方法是什么?
【问题讨论】:
FWIW 在您的决策过程中要非常小心,因为如果您失败,它可能会对您的职业生涯产生长期影响。我在 NHibernate 方面拥有超过一年的经验,在我使用 NHibernate 而非普通应用程序的生产中拥有完整的企业应用程序之前的两年。如果有机会我本可以早点完成,我相信我会做的,但事后看来,我认为在我拥有近 2 年的 NHibernate 经验之前,我无法让该项目成功. 那么我在这里寻找什么样的陷阱? nHibernate 的想法是总体上节省时间并减轻问题而不是增加问题。 Atm,我知道使用 WCF 会破坏 nHibernate 的一些功能,但是使用 Respository 模式和 DTO 解决了这个问题,我的计划是在 BL 中定义我的业务对象以及映射文件,然后在 DAL 中使用 Respository 模式,这是个好计划吗? 我对 nhibernate 印象深刻,我们现在有一个中等到轻度复杂的项目 (asp.net MVC) 在上面运行,但它需要一些时间才能使 hql 正确。 (有时我们不得不作弊并使用原始 SQL - 由于缺乏知识)我还使用了经典的映射/实体绑定和旧的 skool php/asp 和 sql spagetti,在其他项目中我们尝试了 ADO.NET 然后Java 数据对象。现在是给我印象最深的 Nhibenrate。 【参考方案1】:我对 nHibernate 的个人经验使我决定数据访问层变得如此之薄,以至于将其与业务逻辑分开对我来说毫无意义。您的大部分数据访问代码已经被分成 xml 文件(或其他各种独特的方法,如 Fluent nHibernate),并且由于几乎透明地处理连接,您使用条件对象的查询很少超过几行。
【讨论】:
这有点像我在想事情可能会发生的事情,目前我的想法是这样的...... 我在业务层中创建了代表我的业务对象的 POCO,例如客户、订单等,以及添加我的 Hibernate 映射。然后我利用 IRespository 模式为每个适当的对象创建一个存储库,例如CustomerRespository、OrderRespository 等抽象出任何允许 WCF 轻松传递对象的 nHibernate guff?在我的数据层中,我包含了适当的 Hibernate 会话管理(通过单例?)和处理实际数据层中 nHibernate 方法的 AbstractRepository 类。 这是我(很快)得出的结论,DAL 抽象的好处仍然存在,BL 将容纳业务对象、映射文件和相关的存储库【参考方案2】:我怀疑你想多了。 nHibernate 基本上是一个非常简单的工具;它的基本作用是管理数据库中记录与数据模型中类似结构化对象之间的序列化。基本上就是这样。没有什么说不能将 Hibernate 对象封装在业务层对象中进行验证;这很好。但是要明白验证和序列化的操作是根本不同的; Hibernate 管理序列化组件,并且做得很好。您可以将 Hibernate-serializable 对象视为有效的“原子”对象。
基本上,您想要的是:nHibernate 是您的数据访问层。 (当然,您可以在数据访问层中使用其他数据访问方法,但是如果您要使用 Hibernate,您应该保持基本的 Hibernate 数据设计,即执行相对简单的记录映射的简单对象反对。)如果您的设计要求您使用不能很好地映射到 Hibernate 的不同设计(依赖于多个重叠表的深度复合对象),您可能不得不放弃使用 Hibernate;否则,只需使用 nHibernate 所暗示的简单 POCO 方法。
【讨论】:
-1 希望我可以 -10 声明“nHibernate 基本上是一个非常简单的工具”,这是完全不准确的。 NHibernate 的会话管理是我在软件开发中必须处理的最复杂的关系之一。 和另一个 -1 表示当您的设计需要深度复合对象时应该放弃 Nhibernate。与我尝试过的许多其他工具相比,Nhibernate 让这变得轻而易举 @Noctris 我实际上必须同意关键字 Deeply 的这一点,使用 NHibernate,您很少希望在对象中进行超过 2-3 个嵌套,因为之后您的 sql 查询可能会结束有几十个连接。一旦您开始进行继承,其中 Contact 继承自 Person 并且 Employee 继承自 Contact 时,这很容易看出,Person 对象具有地址和电话的集合。此时您有 5 或 7 个表,具体取决于您是否将集合建模为多对多。 @Noctris:别做个混蛋。声明是“如果您的设计要求您使用不能很好地映射到 Hibernate 的不同设计,您可能不得不放弃使用 Hibernate”;我没有“声明 OP 应该放弃 Hibernate”。两个预选赛; IF 和 MIGHT 并不是“声明你应该放弃 Hibernate”。 我认为你们两个读这篇文章太多了。我对这些陈述的理解与你们两个完全不同。 1)一个工具可以很简单,但仍然需要很多技巧才能掌握。 2) nHibernate 可能不适合所有类型的应用程序。【参考方案3】:我喜欢让架构出现,但如果我今天使用 NHibernate 启动它,这就是我在典型的 ntier asp.net mvc 项目上的启动架构的样子。
首先,我会尝试将尽可能多的域代码保留在控制器之外。因此,我将在控制器(或背后的代码)调用的业务层上创建一个服务层/外观。我会将我的对象分为两种类型:1) 具有在写入端使用的业务行为的对象,以及 2) 用于显示数据和获取初始数据输入的 ViewModel / DTO 对象。这些 DTO 将具有所有特定于视图的关注点,例如简单的验证属性等...... DTO 可以有自己的 NHibernate 映射,或者可以使用 NHibernate 的 AliasToBean 功能进行投影。一旦它们在操作中通过控制器,它们将被映射到业务对象。
就数据访问层而言,我可能会直接在服务层中使用 NHibernate。除非我知道我必须能够换出 ORM,否则我不会使用存储库模式。 NHibernate 已经是一个持久化抽象。将存储库放在它上面会让你放弃很多功能。
【讨论】:
“在它上面放置一个存储库会让你放弃很多功能。”我完全不同意这一点,在它之上实现存储库模式是轻松获得 NHibernate 优点的好方法。我有一个关于这部分的博客,这是我用 NHibernate 实现的最好的事情。 dotnetchris.wordpress.com/2010/03/15/… 当我说存储库模式时,我更多地考虑的是与 ORM 无关的模式。我看到你的是 NHibernate 特定的,因此你没有放弃任何功能。我会使用类似的东西,或者更有可能是查询对象模式(基本上是一堆超特定的 repos)。【参考方案4】:我的 02 美分(因为没有万能的答案):
DAL 应该只负责数据检索和持久化。
您可以拥有一个包含模型(对象)的库,这些模型由 DAL 填充,但松耦合(理论上,您应该能够使用其他技术编写新的 DAL 并将其插入而不是 NHIBERNATE 的,即使你不打算)
对于客户 BL 谈话,我会认真建议views/dto's 以避免模型与客户耦合(信任,我.. 我正在清理这样的应用程序,这是地狱)
无论如何.. 我说的是我们在这里使用的情况,它遵循这种结构:
客户端(winforms 和 web) 查看/演示者 使用消息的 WCF 服务 BL DAL
【讨论】:
【参考方案5】:我在生产中拥有基于 NHibernate 的应用程序,虽然它比大多数 DAL 更好,但我现在再也不能推荐任何人使用 NHibernate。与会话一起执行任何高级应用程序所需的复杂性简直是荒谬的。对于做简单的应用程序来说,NHibernate 对企业应用程序来说是微不足道的,复杂性是超乎想象的。
在这一点上,我决定根据范围使用 3 种不同的选择来解决数据访问问题,使用文档数据库(目前特别是 Raven)进行全面应用程序,使用 LinqToSql 进行中等数量的数据访问,以及用于微不足道的数据访问访问我实际上使用原始 ADO.NET 连接取得了巨大成功。
作为参考,这些陈述是在我使用 NHibernate 进行了 2 年多的开发时间之后,每次我觉得我完全理解 NHibernate 时,我都会遇到一些新的限制或我必须做的巨型活动扳手处理。这也让我意识到我开始设计与 NHibernate 相关的应用程序,这是我使用 ORM 以使我的应用程序设计不受数据库支配的首要原因之一。
不必处理具有 NHibernate 复杂性的会话管理对我来说是迁移到 RavenDB 的最大好处之一。使用 Raven,您几乎不需要管理会话,除非您进行极端性能优化或使用批处理操作。
【讨论】:
我不确定您在谈论会话的复杂程度。至少对于 Web 应用程序,我发现您可以在各种 nHibernate 博客上看到人们在 Web 上使用的 HybridSessionBuilder 使得会话管理相当轻松。 jeffreypalermo.com/blog/… 尝试在网络环境中使用 NHibernate 实现长期保护模式,两年后我已经放弃并接受了 NHibernate 根本不可能。 这家伙似乎认为他做到了:dotnetchris.wordpress.com/2009/12/18/… @Spencer 感谢您提醒我在我的帖子上贴一张巨大的警告贴纸。以上是关于nHibernate,一个 n 层解决方案 + 请求咨询的主要内容,如果未能解决你的问题,请参考以下文章
使用 NHibernate 和上下文更改数据库设计分层应用程序