代码之家  ›  专栏  ›  技术社区  ›  Joseph Ferris

检测聚合根中实体的更改

  •  3
  • Joseph Ferris  · 技术社区  · 15 年前

    我想看看人们可能采取了什么方法来检测作为集合一部分的实体的变化。我有一些有用的东西,但我并不为此疯狂。基本上,我的存储库负责确定聚合根的状态是否已更改。假设我有一个名为 Book 以及一个被称为 Page 在集合中。一 包含一个或多个 实体,存储在 Pages 收集。

    首先,插入与更新场景是通过检查聚合根及其实体来确定键的存在来完成的。如果该键存在,则假定该对象曾一度保存到基础数据源。这使得它成为更新的候选对象;但是它并不能仅基于实体的更新而确定。对于聚合根,答案是显而易见的,因为只有一个,而且它是唯一的入口点,可以假定键的存在将指示操作。在我的例子中,再次保存聚合根目录本身是一个可接受的场景,这样我就可以捕获修改日期。

    为了帮助促进实体自身的这种行为,我的 EntityBase 类包含两个简单属性: IsUpdated() , IsDeleted() . 这两个都默认为假。我不需要知道它是否是新的,因为我可以根据密钥的存在做出决定,如前所述。实现中的方法(在本例中是页面)将具有更改支持数据集的每个方法。 ISUPDATED() 成真。

    例如,page有一个方法 UpdateSectionName() 它改变了 SectionName 属性,它是只读的。这种方法是一致使用的,因为它允许在执行该数据设置的方法中使用验证器的逻辑连接点(防止实体进入无效状态)。最终的结果是我必须 this.IsUpdated() = true; 在方法的末尾。

    当将聚合根发送到存储库中 Save() (逻辑开关 Insert() Update() 操作),然后它可以在 收藏在 ,查找具有以下三种方案之一的任何页面:

    1. 没有钥匙。一 不插入任何键。
    2. IsDeleted = true; 删除比更新更重要,删除将被提交-忽略 第页 .
    3. IsUpdated = true; 将提交该页的更新。

    这样做可以防止我盲目地更新页面集合中的所有内容,例如,如果书中有几百个页面实体,这可能会让人望而生畏。我一直在考虑检索这本书的副本,并进行比较,只提交检测到的更改(基于存在和/或比较的插入、更新和删除),但这似乎是一种非常健谈的方式。

    主要缺点是开发人员必须记住在实体中的每个方法中设置isupdated。忘记一个,它将无法检测该值的更改。我已经玩弄了一种自定义的后备存储的想法,它可以透明地标记更改的时间戳,而这反过来又可以 IsUpdated 存储库可用于聚合更新的只读属性。

    存储库使用的是一个工作模式实现单元,它的操作基于添加聚合根时生成的时间戳。由于可能有多个实体排队等待操作,因此实体操作将在执行实体所属的聚合根操作之后立即进行汇总和执行。我可以看到更进一步,创建另一个工作单元来处理实体操作,并基于实体中使用的某种事件跟踪(这就是我假设市场上的一些ORM产品实现类似功能的方式)。

    不过,在我继续朝这个方向前进之前,我想听听关于这方面的想法/建议/经验。

    编辑: 一些可能有助于了解的附加信息:

    1. 我现在使用的语言是C,尽管我尽量保留尽可能多的语言特定信息,因为这更多的是一个理论上的讨论。
    2. 存储库/服务/实体/等的代码基于Tim McCarthy在其书中的概念,“.NET域驱动的C设计”和 CodePlex . 它提供了对所采用方法类型的可运行理解,尽管我正在使用的方法基本上是从头开始重写的。
    1 回复  |  直到 15 年前
        1
  •  1
  •   Joseph Ferris    15 年前

    简言之,我的回答是我按照我的提议去做。虽然我确信还有改进的余地,但它是有效的。这些变化实际上花了很少的时间,所以我觉得在这种情况下,我并没有偏离基斯或雅格尼的原则太远。-)

    我仍然觉得操作上有时间相关问题的空间,但是我应该能够在存储库实现中解决这些问题。不是理想的解决方案,但我不确定是否值得重新设计车轮来纠正一个可以在比修复时间更短的时间内避免的问题。