2017-10-15 67 views
0

我目前正在尝试在DDD中编写应用程序,以允许创建,更新和删除实体。对实体的更改必须得到另一个人的批准。应用程序还必须跟踪对实体进行了哪些更改。简化的域模型看起来像这样:如何访问聚合边界内的实体

enter image description here

该应用程序有含ChangeSetEnityEntityHistory一个界上下文其中ChangeSet是聚合根。因为Entity在没有ChangeSet的情况下不应该被改变,并且ChangeSet应该与编辑的实体一起被保存在一个事务中。在那个账户上,我设计了一个聚合体。

的设计工作还不错时创建新的实体:

private void CreateChangeSet() 
{ 
    var repository = new ChangeSetRepository(); 
    var entities = new List<Entity> 
    { 
     new Entity(Guid.NewGuid(), "Test1", new TagStatus(1, EntityState.Pending)); 
    }; 
    var changeSet = new ChangeSet("a user", "Added a new entity", DateTime.Now, ApprovalState.Submitted, entities); 
    repository.Insert(changeSet); 
} 

然而,出现在我的设计问题,当我试图编辑实体发生:据我所知

private void EditEnity() 
{ 
    var repository = new ChangeSetRepository(); 
    var entity = repository.GetEntityByName("Test1");  
    entity.AssignName("a new name"); 
    var entities = new List<Entity>{entity}; 

    var cs = new ChangeSet("a user", "Added a new entity", DateTime.Now, ApprovalState.Submitted, entities); 
    repository.Insert(cs); 
} 

一个仓库应该只返回集合,这意味着为了更改Entity我必须首先搜索ChangeSet,这是没有意义的。即使执行更改只是聚合根目录,返回聚合的子实体是否是不良做法?

我在网上搜索了一个答案,很多人都指出这种查询可以指出一个错误的聚合设计。这让我再次想到,如果不是一个总计,我需要两个总计一个用于ChangeSet,另一个包含EntityEntityHistory。我应该使用两个集合而不是一个?如果是的话,我怎么能在一次交易中做到这一点?

两个聚合的进一步指示是用户界面要求,如“用户想要查看实体的更改历史记录”或“显示视图中的所有实体”。一方面,这表明两个集合体另一方面,我有一种感觉,ChangeSetEntities应该真的属于一起。

综上所述,我的问题:

  • 我应该在我的设计使用一个或两个聚集?
  • 如果一个聚合:即使只通过聚合根执行更改,是否返回聚合的子实体是不好的做法?
  • 如果两个聚合:如何将ChangeSet和关联的Entities保存在一个事务中?
+0

为什么你不看事件采购,事件将成为你的历史,你不需要另外做任何事情? –

+0

我会遵循Alessandro Santini的建议,并尝试一下活动。我有一种感觉,即变更集不适合模型,事件采购可以解决这个问题。 – MUG4N

+1

这里的问题是版本控制问题更具技术性和通用性。因此,将其建模为领域模型的一部分可能是过度的。您还可以考虑数据库版本控制模型,例如RavenDb有一个版本控制软件包,可以保留一定数量的文档版本。这也是一种有效的方法。 –

回答

3

TL; DR:

  • 您应该使用一个实体。
  • 是的,这是不好的做法,因为行为应该暴露在总量;同样,重建Entity将要求Entity知道如何查询ChangeSet;除非您在服务级别上进行编排,否则这不是很棒的设计。
  • 你不应该这样做,作为一个聚合根代表,恕我直言,一个交易界线

更多的想法

如果我理解正确,你正在做什么事件采购不自然,增加审批的工作流程。在Event Store中的Events与您定义的ChangeSet大致相同。

如果这是正确的,你可以优雅地在ES通过模拟这种:

  • 编辑实体的API,作为输入的变化为Entity
  • 的API批量:
    • 从API输入构建ChangeEntityCommand(命令可能无法验证);
    • 检索Entity;
    • 调用Entity集合中对应的Handler,集合依次发出ChangeQueuedForApprovalEvent
    • 提交实体在EventStore
  • 一种EventHandler将拦截上面的事件并采取更新批准视图照顾。

当审批者发出绿灯时,类似的流程将发出包含前一事件的相同数据的ChangeApprovedEvent。这个事件实际上是转换Entity的事件。

最后,我不相信ChangeSet建模确实适合DDD,因为它无法捕捉到更改的意图。

希望这有助于您的项目,祝您好运。