【发布时间】:2011-03-27 12:58:51
【问题描述】:
我开始考虑在断开连接的应用程序中跟踪复杂对象图的变化。我已经找到了几个解决方案,但我想知道是否有任何最佳实践或您使用什么解决方案以及为什么?我将同样的问题传递给MSDN forum,但我只收到一个答案。我想从其他开发人员的经验中获得更多答案。
这个问题与 .NET 有关,因此对于实现细节的答案,我更喜欢与 .NET 世界相关的答案,但我认为这在其他平台上是相同的。
我的案例中的理论问题在多层架构(目前不一定是n层)中定义如下:
- 使用 ORM 处理持久性的存储库层(ORM 工具目前无关紧要,但很可能是 Entity Framework 4.0 或 NHibernate)。
- 表示域对象的纯类集(持久无知 = POCO,相当于 Java 世界中的 POJO)。存储库保存这些类并将它们作为查询结果返回。
- 与域实体一起工作的域服务集。
- 定义业务逻辑网关的外观层。它在内部使用存储库、域服务和域对象。域对象不暴露——每个外观方法使用一组专门的数据传输对象作为参数和返回值。将域实体转换为 DTO 是每个外观方法的责任,反之亦然。
- 使用外观层和 DTO 的现代 Web 应用程序 - 我称之为断开连接的应用程序。一般来说,未来设计可能会发生变化,因此外观层将被 Web 服务层包裹,而 Web 应用程序将使用该服务 => 过渡到 3 层(Web、业务逻辑、数据库)。
现在假设域对象之一是 Order,它具有 Order 详细信息(行)和相关 Orders。当客户请求编辑订单时,它可以修改订单、添加、删除或修改任何订单详细信息以及添加或删除相关订单。所有这些修改都是在 Web 浏览器中的数据上完成的——javascript 和 AJAX。因此,当客户端按下保存按钮时,所有更改都会一次性提交。问题是如何处理这些变化?存储库和 ORM 工具需要知道哪些实体和关系被修改、插入或删除。我以两个“最佳”解决方案结束:
将 DTO 的初始状态存储在隐藏字段中(在最坏的情况下存储到会话中)。当收到保存更改的请求时,根据收到的数据创建新的 DTO,并根据持久的数据创建第二个 DTO。合并这两个并跟踪更改。将合并的 DTO 发送到外观层,并使用收到的有关更改的信息来正确设置实体图。这需要在域对象中进行一些手动更改跟踪,以便可以从头开始设置更改信息,然后将其传递到存储库 - 这是我不太满意的一点。
根本不跟踪 DTO 中的更改。在外观层接收修改的数据时,创建修改的实体并从存储库加载实际状态(通常是对数据库的附加查询 - 这是我不太满意的一点) - 合并这两个实体并通过 ORM 工具提供的实体代理自动跟踪更改(实体框架 4.0 和 NHibernate 允许这样做)。并发处理需要特别注意,因为实际状态不必是初始状态。
你怎么看?你有什么建议吗?
我知道可以通过在某些应用程序层上使用缓存来避免其中一些挑战,但这是我目前不想使用的东西。
我对这个话题的兴趣更加浓厚。例如,假设应用程序采用 3 层架构并且客户端(Web 应用程序)不会用 .NET 编写 = DTO 类不能被重用。跟踪 DTO 上的更改会困难得多,因为这需要其他开发团队在他们的开发工具中正确实施跟踪机制。
相信很多应用都需要解决这些问题,请分享经验。
【问题讨论】:
标签: .net architecture orm dto