我想看看人们可能采取了什么方法来检测作为集合一部分的实体的变化。我有一些有用的东西,但我并不为此疯狂。基本上,我的存储库负责确定聚合根的状态是否已更改。假设我有一个名为
Book
以及一个被称为
Page
在集合中。一
书
包含一个或多个
页
实体,存储在
Pages
收集。
首先,插入与更新场景是通过检查聚合根及其实体来确定键的存在来完成的。如果该键存在,则假定该对象曾一度保存到基础数据源。这使得它成为更新的候选对象;但是它并不能仅基于实体的更新而确定。对于聚合根,答案是显而易见的,因为只有一个,而且它是唯一的入口点,可以假定键的存在将指示操作。在我的例子中,再次保存聚合根目录本身是一个可接受的场景,这样我就可以捕获修改日期。
为了帮助促进实体自身的这种行为,我的
EntityBase
类包含两个简单属性:
IsUpdated()
,
IsDeleted()
. 这两个都默认为假。我不需要知道它是否是新的,因为我可以根据密钥的存在做出决定,如前所述。实现中的方法(在本例中是页面)将具有更改支持数据集的每个方法。
ISUPDATED()
成真。
例如,page有一个方法
UpdateSectionName()
它改变了
SectionName
属性,它是只读的。这种方法是一致使用的,因为它允许在执行该数据设置的方法中使用验证器的逻辑连接点(防止实体进入无效状态)。最终的结果是我必须
this.IsUpdated() = true;
在方法的末尾。
当将聚合根发送到存储库中
Save()
(逻辑开关
Insert()
或
Update()
操作),然后它可以在
页
收藏在
书
,查找具有以下三种方案之一的任何页面:
-
没有钥匙。一
页
不插入任何键。
-
IsDeleted = true;
删除比更新更重要,删除将被提交-忽略
第页
.
-
IsUpdated = true;
将提交该页的更新。
这样做可以防止我盲目地更新页面集合中的所有内容,例如,如果书中有几百个页面实体,这可能会让人望而生畏。我一直在考虑检索这本书的副本,并进行比较,只提交检测到的更改(基于存在和/或比较的插入、更新和删除),但这似乎是一种非常健谈的方式。
主要缺点是开发人员必须记住在实体中的每个方法中设置isupdated。忘记一个,它将无法检测该值的更改。我已经玩弄了一种自定义的后备存储的想法,它可以透明地标记更改的时间戳,而这反过来又可以
IsUpdated
存储库可用于聚合更新的只读属性。
存储库使用的是一个工作模式实现单元,它的操作基于添加聚合根时生成的时间戳。由于可能有多个实体排队等待操作,因此实体操作将在执行实体所属的聚合根操作之后立即进行汇总和执行。我可以看到更进一步,创建另一个工作单元来处理实体操作,并基于实体中使用的某种事件跟踪(这就是我假设市场上的一些ORM产品实现类似功能的方式)。
不过,在我继续朝这个方向前进之前,我想听听关于这方面的想法/建议/经验。
编辑:
一些可能有助于了解的附加信息:
-
我现在使用的语言是C,尽管我尽量保留尽可能多的语言特定信息,因为这更多的是一个理论上的讨论。
-
存储库/服务/实体/等的代码基于Tim McCarthy在其书中的概念,“.NET域驱动的C设计”和
CodePlex
. 它提供了对所采用方法类型的可运行理解,尽管我正在使用的方法基本上是从头开始重写的。