代码之家  ›  专栏  ›  技术社区  ›  Ladislav Mrnka

复杂对象图的变化跟踪

  •  10
  • Ladislav Mrnka  · 技术社区  · 14 年前

    MSDN forum 但我只得到一个答案。我想有更多的答案可以借鉴其他开发人员的经验。

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

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

    • 使用ORM处理持久性的存储库层(ORM工具目前并不重要,但很可能是entityframework4.0或NHibernate)。
    • 一组表示域对象的纯类(persistent nullent=POCO,相当于Java世界中的POJO)。存储库持久化这些类并将它们作为查询结果返回。
    • 定义业务逻辑网关的Facade层。它在内部使用存储库、域服务和域对象。域对象不公开-每个facade方法使用一组专门的数据传输对象作为参数和返回值。每个facade方法负责将域实体转换为DTO,反之亦然。

    现在假设其中一个域对象是Order,它有订单细节(行)和相关的订单。当客户请求编辑订单时,它可以修改订单、添加、删除或修改任何订单详细信息以及添加或删除相关订单。所有这些修改都是在web浏览器中的数据上完成的—javascript和AJAX。因此,当客户端按下save按钮时,所有更改都将在一次快照中提交。问题是如何处理这些变化?存储库和ORM工具需要知道修改、插入或删除了哪些实体和关系。我最后给出了两个“最佳”解决方案:

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

    我知道在某些应用程序层上使用缓存可以避免其中一些挑战,但这是我目前不想使用的。

    我对这个话题更感兴趣。例如,假设应用程序采用3层体系结构,而客户机(web应用程序)将不在.NET=DTO中编写,这样类就不能被重用。跟踪DTO上的更改要困难得多,因为这需要其他开发团队在他们的开发工具中正确地实现跟踪机制。

    2 回复  |  直到 14 年前
        1
  •  3
  •   Adrian K    14 年前

    一切都是为了责任。

    一方面,这似乎效率低下,但由于数据量并不庞大,这不是一个问题;另一方面,由于过程简单得多,所以“移动部件”更少,出错的可能性也更小。

    • DI

    • DTO是在一个公共类中定义的,该类具有很少的依赖关系。

    • 我故意限制为特定对象创建的DTO的数量(比如“Order”)——但同时如果有充分的理由,我会创建新的。通常我会有一个“fat”DTO,它包含该对象的大部分/所有可用数据,我也可能会有一个更精简的DTO,它被设计用于集合(用于列表等)。在这两种情况下,这些DTO都是pureyl,用于返回用于“阅读”的信息。你必须牢记责任——当BL请求数据时,它通常不会试图同时写回数据;因此,DTO是“只读的”这一事实更多地是为了符合干净的接口和体系结构,而不是业务规则。

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

    )照吩咐去做。

        2
  •  3
  •   carsten.alder    13 年前

    我们的体系结构与您的非常相似,但是在客户机和服务器上使用一个Silverlight客户机,它包含相同的域对象(没有确切的-代码是共享的)。我们架构的要点是

    • 客户机拥有域模型,并且使用我自己实现的跟踪框架跟踪更改(它使用AOP以便我可以在客户机端使用POCOs;我不知道这方面的框架,我希望域模型是持久的
    • 在服务器端(服务层由wcfwebservices实现),dto被转换为域对象并附加到ORM(在本例中是NHibernate)。因为这个附件过程,我需要跟踪状态。其他的改变可以通过ORM来完成和持久化

    目前很难将复杂的图附加到ORM上,但我希望原因是我们在使用NHibernate方面没有太多经验。

    我们还没有完成,但似乎很有希望。

    对于数据访问,我们尝试使用WCF数据服务。但我不认为我们会使用它们,因为一个需求就是使用DataContract。这导致了从基于DataContract的LINQ查询到基于域对象的LINQ查询的转换。如果域模型和datacontract有很大的不同(在某些迭代中就是这样),那么这并不方便,也很难实现。

    有什么考虑吗?