【问题标题】:What are the 'big' advantages to have Poco with ORM?Poco 与 ORM 的“大”优势是什么?
【发布时间】:2011-02-07 19:42:48
【问题描述】:

我想到的一个优点是,如果您使用 Poco 类进行 Orm 映射,如果两者都支持 Poco,您可以轻松地从一个 ORM 切换到另一个。

拥有不支持 Poco 的 ORM,例如映射是使用 DataObjects.Net Orm 之类的属性完成的,对我来说不是问题,Poco 支持的 Orms 及其生成的代理实体也是如此,您必须知道实体实际上是绑定到某些上下文/会话的 DAO 对象,例如序列化是一个问题,等等。

【问题讨论】:

    标签: c# orm


    【解决方案1】:

    POCO 是关于松散耦合和可测试性的。

    因此,当您进行 POCO 时,您可以单独测试您的领域模型(例如,如果您正在做 DDD)。您不必担心它是如何持久化的。您不需要存根上下文/会话来测试您的域。

    另一个优点是泄漏的抽象更少。因为持久性问题不会被推送到域层。所以你正在执行 SRP 原则。

    我可以看到的第三个优势是,使用 POCO 你的领域模型更加进化和灵活。与将新功能耦合到持久性相比,您可以更轻松地添加新功能。

    例如,我在做 DDD 时使用 POCO,但对于某些类型的应用程序,您不需要做 DDD(如果您正在做基于小数据的应用程序),所以关注点不一样。

    希望对你有帮助

    【讨论】:

    • +1 我认为这是正确的,但我们应该始终牢记,松耦合还有许多其他用途,而不仅仅是实现可测试性:blog.ploeh.dk/2010/04/07/…
    • 这个泄漏的抽象到底是什么?如果我基于我的 EF 模型构建视图,有人可以通过操作回发数据来删除条目吗?或者这只是公司说的一种好方法,我不信任你,因为当我不想要你的时候你可能会删除记录。我为什么要构建整个项目。它既愚蠢又烦人,毫无意义,花费 80% 的时间编写抽象并前后重新映射定义良好的模型,在 4 个地方更改相同的东西。我认为不需要 POCO,除非您编写类似 CMS 之类的东西,否则……没用?!
    • 这取决于上下文。我并不是说每次都必须这样做。有很多例子说明 CRUD 项目如何在没有额外开销的情况下运行良好。上下文是您的业务。如果您正在构建参考(保存编辑数据),您可能只想使用这种 CRUD 方法。没关系。但是,当您拥有丰富的域模型 WITH 行为时,映射值得考虑,因为它将您的域与持久性问题解耦。
    【解决方案2】:

    没有。观点。人们喜欢到处乱扔的所有优势都是在大范围内不重要的优势。我更喜欢实体对象的强大基类,它实际上包含许多集成代码(例如在属性更改时抛出属性更改事件),而不是自己编写所有这些东西。请注意,在“LINQ”或“ObjectSpaces”甚至存在之前,我确实为 .NET 编写了一个(当时市售的)ORM。我已经使用了 15 年的 O/R 映射器,但从未发现 POCO 真的值得为此付出麻烦。

    也就是说,由于其他原因,属性可能不好。这些天我更喜欢 Fluent NHibernate 方法 - 用属性启动了我自己的(现已退休的)映射器,然后转移到基于 XML 的文件。

    “POCO 让我一无所获”的主题主要来自实体不是普通对象的观点。它们有很多额外的功能以及限制(如查询速度等),用户无论如何都应该注意这些。尽管有 LINQ,但 ORM 无论如何都不可替代 - 如果您开始使用它们真正有趣的更高功能,那就不要了。所以,最后你得到了 POCO,但仍然被基类和左右不同的语义所吸引。

    我发现大多数 POCO 的支持者(例如:“必须有”,而不是“会很好”)通常没有认为他们的论点达到了真正的目的。你会得到各种非常糟糕的想法,几乎是在“存储过程比动态 SQL 更快”的水平上——这些想法根本不成立。比如:

    • “我希望在不需要保存数据库的情况下使用它们”(使用单独的对象池,从不提交),
    • “我可能希望在基类中拥有自己的功能(ORM 应该分配没有功能的抽象实体类,因此将您的 OWN 基类放在 ORM 之一之下)
    • “我可能想用另一个 ORM 替换”(所以永远不要使用任何更高的功能,希望 ORM API 兼容,然后您可能仍需要重写大部分内容)。

    一般来说,POCO 人们也忽略了真正要使其正确的大量工作 - 诸如事务对象更新之类的东西。基类中有大量代码。一些 .NET 接口很难在 POCO 级别上实现,但如果您可以绑定到 ORM 会容易得多。

    在这里担任 Thomas Jaskula 的职位:

    POCO 都是关于松散耦合和 可测试性。

    假设您可以在没有它的情况下测试数据绑定?可测试性是模拟框架的东西,有真正强大的甚至可以“重定向”方法调用。

    所以当你在做 POCO 时,你可以 测试你的领域模型(如果你是 做 DDD 例如)孤立。 你不必担心它是怎么做的 持续存在。你不需要存根 用于测试您的域的上下文/会话。

    其实不然。持久性应该是任何领域模型测试的一部分,因为领域模型是要被持久化的。您始终可以通过不提交更改来测试非持久性场景,但许多测试将涉及持久性和失败(例如,具有无效/丢失数据的发票无效,无法写入磁盘)。

    另一个优点是 更少泄漏的抽象。因为 持久性问题不会被推到 域层。所以你正在执行 SRP 原则。

    其实没有。正确的域模型永远不会在实体中具有持久性方法。这是一个以(user.Save())开头的垃圾ORM。 OTOH 基类将处理诸如验证 (IDataErrorInfo) 之类的事情,处理持久字段上的属性更新事件,通常可以为您节省大量时间。

    正如我之前所说,您应该拥有的某些功能很难用变量作为数据存储来实现 - 例如将实体置于更新模式、进行一些更改然后回滚的能力。不需要 - 如果在他们的数据网格中可用,请告诉使用该功能的 Microsoft(您可以更改某些属性,然后点击转义以回滚更改)。

    我可以看到的第三个优势是 做 POCO 你的领域模型更多 进化和灵活。你可以加 新功能比以前更容易 耦合到持久性。

    非争论。您不能在不处理持久性的情况下将字段添加到 peristet 类,并且可以将非持久性功能(方法)添加到非 poco 类,就像添加到 poco 类一样。

    一般来说,我的非 POCO 基类执行以下操作:

    • 处理属性更新和 IDataErrorInfo - 无需用户为 ORM 可以处理的字段和项编写一行代码。
    • 处理对象状态信息(新建、更新等)。这是恕我直言的内在信息,也经常被推送到用户界面。请注意,这不是“保存”方法,而只是一个 EntityStatus 属性。

    并且它包含许多可覆盖的方法,实体可以使用这些方法来扩展行为而无需实现(公共)接口 - 因此这些方法实际上是实体私有的。它还有一些更多的内部属性,例如访问负责实体的“对象管理器”,这也是请求其他实体(提交查询)的点,这有时是需要的。

    【讨论】:

    • 我想你不明白我想说什么:如果你使用 POCO,你至少是在尝试实现一个领域模型。当我想测试我的 Domain 的行为时,为什么我应该为模拟框架而烦恼?如果您依赖于 mockings 框架,那么您假设不应该关心域的设计方式。做 POCO,我假设持久性问题不在域模型中的实体中,因此不会有来自持久性的泄漏抽象。第三,你的领域模型并不总是数据库的镜像……
    • ...即使应该更新映射,您也可以向您的 DM 添加行为,而不受持久性问题的限制。
    • 好吧,说真的 - 我在没有任何嘲笑的情况下测试我的域实体行为(没有持久性)。我只是从不最后提交;)所以 - 没有查询,没有提交更新 = 没有生成 sql。
    • 最后,一个非常有意义的帖子。
    【解决方案3】:

    ORM 中的 POCO 支持完全是关注点分离,遵循 Single Responsibility Principle。借助 POCO 支持,ORM 可以直接与域模型对话,而无需使用特定于数据访问的代码“混淆”域。这确保了域模型旨在仅解决与域相关的问题,而不是数据访问问题。

    除此之外,POCO 支持可以更轻松地单独测试对象的行为,而无需数据库、映射信息甚至对 ORM 程序集的引用。拥有“独立”对象的能力可以显着简化开发,因为对象易于实例化且易于预测。

    此外,由于 POCO 对象未绑定到数据源,因此无论它们是从您的主数据库、备用数据库、平面文件还是任何其他进程加载的,您都可以同等对待它们。尽管这似乎不会立即带来好处,但无论来源如何都一视同仁地对待您的对象可以使行为易于预测和使用。

    我为我最近的 ORM 选择了 NHibernate,因为它支持 POCO 对象,它处理得很好。它适合项目遵循的领域驱动设计方法,并在数据库和领域之间实现了很好的分离。

    能够切换 ORM 工具并不是 POCO 支持的真正理由。尽管您的类可能与 ORM 没有任何直接依赖关系,但它们的行为和形状将受到 ORM 工具和它所映射到的数据库的限制。更改 ORM 与更改数据库提供程序一样重要。一个 ORM 中总会有一些功能在另一个 ORM 中不可用,并且您的域类将反映功能的可用性或缺失。

    在 NHibernate 中,您需要将所有 publicprotected 类成员标记为 virtual 以启用对延迟加载的支持。这个限制虽然没有显着改变我的领域层,但对其设计产生了影响。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-25
      • 2014-06-03
      • 2016-07-03
      • 2011-07-19
      • 2014-08-03
      • 2015-03-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多