2009-09-14 68 views
1

我期待看到人们可能采取了哪些方法来检测属于其聚合的一部分的实体中的更改。我有一些工作,但我并不是疯了。基本上,我的仓库负责确定聚合根的状态是否已更改。假设我的聚合根中有一个名为Book的聚合根和一个名为Page的实体。 A Book包含一个或多个Page实体,存储在Pages集合中。检测聚合根目录中实体的更改

首先,插入与更新方案是通过检查聚合根和它的实体来确定密钥的存在来完成的。如果键存在,则假定该对象一次被保存到基础数据源。这使得它成为更新的候选者;但它不是基于单独的实体而确定的。对于聚合根来说,答案是显而易见的,因为只有一个,并且它是单一的入口点,所以可以假设关键存在将决定操作。在我的情况下,可以接受的方案是再次保存聚合根本身,以便我可以捕获修改日期。

为了便于实体本身的这种行为,我的EntityBase类包含两个简单属性:IsUpdated(),IsDeleted()。这两个都默认为false。如前所述,我不需要知道它是否是新的,因为我可以根据密钥的存在做出决定。实现方法(在本例中为Page)将使每种方法将后备数据集IsUpdated()更改为true。

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

当聚合根被发送到存储库的Save()(一个逻辑开关进行控制,一个Insert()Update()操作)时,它可以然后遍历Pages集合中的Book,寻找具有一个三者的任何页方案:

  1. 没有钥匙。没有密钥的Page将被插入。
  2. IsDeleted = true;删除胜过更新,并且删除将被提交 - 忽略Page的任何更新。
  3. IsUpdated = true;页面会提交更新。

这样做可以防止我盲目更新Pages集合中的所有内容,例如,如果书中有几百个Page实体,那么这可能令人望而生畏。我一直在考虑检索本书的副本,并进行比较,只检查变化(根据状态和/或比较插入,更新和删除),但这似乎是一种非常好用的方法。

主要缺点是开发人员必须记住在实体中的每个方法中设置IsUpdated。忘记一个,它将无法检测到该值的变化。我已经提出了某种自定义后备存储的想法,它可以透明地对变更进行时间戳记记录,这又可以使IsUpdated成为存储库可用于聚合更新的只读属性。

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

在我继续朝着这个方向前进的过程中,我很想听到关于这方面的想法/建议/经验。

编辑:一些额外的信息,可能有助于了解:

  1. ,我有工作当前语言是C#,虽然我试图保持尽可能多的特定语言信息进行尽可能,因为这更多是理论上的讨论。
  2. 存储库/服务/实体/等的代码。基于Tim McCarthy的概念,在他的书“.NET域驱动设计与C#”和支持代码CodePlex。它提供了对所采取的方法类型的可运行理解,尽管我所从事的工作基本上已从头改写。

回答

1

总之,我的答案是我用我的建议去。它正在工作,但我确信还有改进的空间。这些变化实际上花费的时间很少,所以我觉得在这种情况下我没有离开KISS或YAGNI校长太远。 :-)

我仍然觉得在操作上有与时间有关的问题,但我应该可以在存储库实现中解决它们。不是最理想的解决方案,但我不确定是否值得重新发明解决问题的方法,可以在比解决问题所需的时间更短的时间内解决问题。