跟踪复杂对象图中的变化 [英] Tracking changes in complex object graph

查看:22
本文介绍了跟踪复杂对象图中的变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始考虑在断开连接的应用程序中跟踪复杂对象图的变化.我已经找到了几种解决方案,但我想知道是否有任何最佳实践或您使用什么解决方案,为什么?我将同样的问题传递给了 MSDN论坛,但我只收到一个答案.我想从其他开发人员的经验中学习更多的答案.

I started to think about tracking changes in complex object graph in disconnected application. I have already found several solutions but I would like to know if there is any best practice or what solution do you use and why? I passed same question to MSDN forum but I received only single answer. I would like to have more answers to learn from experience of other developers.

这个问题与 .NET 相关,所以对于带有实现细节的答案,我更喜欢与 .NET 世界相关的答案,但我认为这在其他平台上也是一样的.

This question is related to .NET so for answers with implementation details I prefer answers related to .NET world but I think this is the same on other platforms.

在我的案例中,理论问题在多层架构(目前不一定是 n 层)中定义如下:

The theoretical problem in my case is defined in multi layered architecture (not necessarily n-tier at the moment) as follows:

  • 使用 ORM 处理持久性的存储库层(ORM 工具目前无关紧要,但很可能是实体框架 4.0 或 NHibernate).
  • 表示领域对象的纯类集(persistent ignorant = POCO,相当于 Java 世界中的 POJO).存储库保留这些类并将它们作为查询结果返回.
  • 使用域实体的域服务集.
  • 外观层定义了业务逻辑的网关.它在内部使用存储库、域服务和域对象.域对象没有公开——每个门面方法使用一组专门的数据传输对象作为参数和返回值.每个门面方法都有责任将域实体转换为 DTO,反之亦然.
  • 使用外观层和 DTO 的现代 Web 应用程序 - 我称此为断开连接的应用程序.一般来说,未来设计可能会发生变化,因此 Facade 层将被 Web 服务层包裹,而 Web 应用程序将使用该服务 => 过渡到 3 层(Web、业务逻辑、数据库).

现在假设域对象之一是具有订单详细信息(行)和相关订单的订单.当客户请求编辑订单时,它可以修改订单,添加、删除或修改任何订单详细信息以及添加或删除相关订单.所有这些修改都是在 Web 浏览器中的数据上完成的 - javascript 和 AJAX.因此,当客户端按下保存按钮时,所有更改都会一次性提交.问题是如何处理这些变化?存储库和 ORM 工具需要知道哪些实体和关系被修改、插入或删除.我以两个最佳"解决方案结束:

Now suppose that one of the domain object is Order which has Order details (lines) and related Orders. When the client requests Order for editation it can modify Order, add, remove or modify any Order detail and add or remove related Orders. All these modifications are done on data in the web browser - javascript and AJAX. So all changes are submited in single shot when client pushes the save button. The question is how to handle these changes? Repository and ORM tool need to know which entities and relationships were modified, inserted or deleted. I ended with two "best" solutions:

  1. 将 DTO 的初始状态存储在隐藏字段中(最坏的情况是会话).当收到保存更改的请求时,根据收到的数据创建新的 DTO,并根据持久化的数据创建第二个 DTO.合并这两个并跟踪更改.将合并的 DTO 发送到外观层,并使用收到的有关更改的信息来正确设置实体图.这需要在域对象中进行一些手动更改跟踪,以便可以从头开始设置更改信息,然后将其传递到存储库 - 这是我不太满意的一点.

  1. Store initial state of DTO in hidden field (in worse case to session). When receiving request to save changes create new DTO based on received data and second DTO based on persisted Data. Merge those two and track changes. Send merged DTO to facade layer and use received information about changes to properly set up entity graph. This requires some manual change tracking in domain object so that change information can be set up from scratch and later on passed to repository - this is the point I am not very happy with.

根本不跟踪 DTO 中的更改.当在门面层接收修改的数据时创建修改的实体并从存储库加载实际状态(通常对数据库进行附加查询 - 这是我不太满意的一点) - 合并这两个实体并通过 ORM 工具提供的实体代理自动跟踪更改(实体框架 4.0 和 NHibernate 允许这样做).并发处理需要特别小心,因为实际状态不必是初始状态.

Do not track changes in DTO at all. When receiving modified data in facade layer create modified entity and load actual state from repository (generally additional query to database - this is the point I am not very happy with) - merge these two entities and automatically track changes by entity proxy provided by ORM tool (Entity framework 4.0 and NHibernate allow this). Special care is needed for concurrency handling because actual state does not have to be the initial state.

你怎么看?你有什么建议吗?

What do you think about that? What do you recommend?

我知道可以通过在某些应用程序层上使用缓存来避免其中一些挑战,但我目前不想使用缓存.

I know that some of these challenges can be avoided by using caching on some application layers but that is something I don't want to use at the moment.

我对这个话题的兴趣更进一步.例如,假设应用程序采用 3 层架构并且客户端(Web 应用程序)不会用 .NET 编写 = DTO 类不能重用.跟踪 DTO 上的更改会困难得多,因为它需要其他开发团队在他们的开发工具中正确实施跟踪机制.

My interest in this topic goes even futher. For example suppose that application goes to 3-tier architecture and client (web application) will not be written in .NET = DTO classes can't be reused. Tracking changes on DTO will than be much harder because it will require other development team to properly implement tracking mechanism in their development tools.

相信很多应用都需要解决这些问题,请大家分享经验.

I believe these problems have to be solved in plenty of applications, please share you experience.

推荐答案

一切都与责任有关.

(我不确定这是否是您想要的答案 - 如果不是,请告诉我,以便我可以更新).

(I'm not sure if this is the sort of answer you're after - let me know if it's not so I can update it).

所以我们在一个系统中有多个层 - 每个层负责不同的任务:数据访问、UI、业务逻辑等.当我们以这种方式构建系统时,我们(除其他外)试图做出未来的改变通过让每个组件负责一项任务来轻松 - 因此它可以专注于一项任务并做得很好.随着时间的推移和需要更改,它还可以更轻松地修改系统.

So we have multiple layers in a system - each is responsible for a different task: data access, UI, business logic, etc. When we architect a system in this way we are (amongst other things) trying to make future change easy by making each component responsible for one task - so it can focus on that one task and do it well. It also makes it easier to modify the system as time passes and change is neeed.

在考虑 DTO 时需要记住类似的想法——如何跟踪变化?"例如.我是这样处理的:BL 负责管理规则和逻辑;鉴于网络的无状态性质(这是我做大部分工作的地方),我只是没有跟踪对象的状态并明确地寻找变化.如果用户将数据传回(要保存/更新),我会将所有数据传回,而不管发生了什么变化.

Similar thoughts need to be in mind when considering the DTO - "how to track changes?" for example. Here's how I approach it: The BL is responsible for managing rules and logic; given the stateless nature of the web (which is where I do most of my work) I'm just not tracking the state of an object and looking explicitly for changes. If a user is passing data back (to be saved / updated) I'll pass the whole lot back without caring what's been changed.

一方面,这可能看起来效率低下,但由于数据量并不大,所以这不是问题;另一方面,由于过程更简单,因此活动部件"更少,出错的可能性也更少.

One one hand this might seem inefficient but as the amounts of data aren't vast it's just not an issue; on the flipside, there's less "moving parts" less can go wrong as the process is much simpler.

我如何将数据传回?-

How I pass the data back? -

  • 我使用 DTO(或者 POCO 会更准确);当我在 BL 和 DAL 之间交换数据(通过接口/DI)时,数据交换为DTO(或它们的集合).具体来说,我将一个结构用于单个实例,并将这些结构的集合用于多个实例.

  • I use DTO's (or perhaps POCO's would be more accurate); when I exchange data between the BL and DAL (via interfaces / DI) the data is exchanged as a DTO (or collection of them). Specifically, I'm using a struct for a single instance and a collection of these structs for multiple.

DTO 定义在一个具有很少依赖项的公共类中.

The DTO's are defined in a common class that has very few dependencies.

我故意限制为特定对象(如订单")创建的 DTO 的数量 - 但同时如果有充分的理由,我会创建新的.通常,我会有一个胖"DTO,其中包含该对象的大部分/所有可用数据,我可能还会有一个更精简的 DTO,旨在用于集合(用于列表等).在这两种情况下,这些 DTO 都是纯粹的,用于返回阅读"信息.你必须牢记责任——当 BL 请求数据时,它通常不会同时尝试写回数据;因此,DTO 是只读"的这一事实更多是为了符合干净的界面和架构,而不是业务规则.

I deliberately try to limit the number of DTO's a create for a specific object (like "Order") - but at the same time I'll make new ones if there is a good reason. Typically I'll have a "fat" DTO which contains most / all of the data available for that object, I'll also probably have a much leaner one that's designed to be used in collections (for lists, etc). In both cases these DTO's are pureyl for returning info for "reading". You have to keep the responsibilities in mind - when the BL asks for data it's usually not trying to write data back at the same time; so the fact that the DTO is "read only" is more about conforming to a clean interface and architecture than a business rule.

我总是为插入和更新定义单独的 DTO - 即使它们共享完全相同的字段.这样,可能发生的最糟糕的情况是重复一些琐碎的代码 - 而不是有依赖项和多个重用案例需要解决.

I always define seperate DTO's for Inserting and Updating - even if they share exactly the same fields. This way the worst that can happen is duplication of some trival code - as opposed to having dependancies and multiple re-use cases to untangle.

最后 - 不要将 DAL 的工作方式与 UI 的工作方式混淆;让 ORM 来做他们的事,仅仅因为他们以给定的方式存储数据并不意味着这是唯一的方式.

Finally - don't confuse how the DAL works with how the UI does; Let ORM's do their thing, just because they store the data in a given way doesn't mean it's the only way.

最重要的是在层之间指定有意义的接口.

The most important thing is to specify meaningful interfaces between your layers.

管理变更是 BL 的工作;让 UI 以最适合您的用户的方式工作,让 BL 弄清楚它想如何处理它,以及 DAL(通过带有 DI) 只是按照它所说的去做.

Managing what's changed is the job of the BL; let the UI work in a way that's best for your users and let the BL figure out how it wants to deal with that, and the DAL (via your nice clean interface with DI) just does what it's told.

这篇关于跟踪复杂对象图中的变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆