2010-03-31 69 views
1

我们有一个复杂的聚合(由于机密性原因而被混淆的敏感名称)。使用存储库模式保存复杂聚合

根R由Ms,As,Cs,Ss的集合组成。 Ms具有其他低级细节的集合。等等等等

[R确实是一个聚集(不公平的建议我们分开吧!)

我们使用延迟加载检索细节。那里没问题。

但是我们正在为如何保存这样一个复杂的聚合而苦苦挣扎。

从查看来电者的观点:

r = repository.find(id); 
r.Ps.add(factory.createP()); 
r.Cs[5].updateX(123); 
r.Ms.removeAt(5); 
repository.save(r); 

我们的竞争对手的解决方案是:

  1. 脏标志 在总合计每个实体都有一个肮脏的标志。存储库中的save()方法遍历树寻找脏对象并保存它们。删除和添加有点棘手 - 特别是在延迟加载的情况下 - 但可行。

  2. 事件侦听器积累更改。 存储库订阅侦听器以进行更改并累积事件。当调用保存时,存储库抓取所有更改事件并将它们写入数据库。

  3. 放弃存储库模式。 实现重载的保存方法分别保存聚合的部分。原始示例将变为:

    r = repository.find(id); r.Ps.add(factory.createP()); r.Cs [5] .updateX(123); r.Ms.removeAt(5); (r.Ps); repository.save(r.Cs); repository.save(r.Ms);

(或更糟)

建议请!我们应该做什么?

+0

我认为你没有使用现成的ORM,它通常会为你照顾这个吗? – JasonTrue 2010-03-31 23:52:38

+0

这是正确的。 – 2010-04-01 00:47:55

回答

0

因此,如果您不想使用ORM,则必须构建自己的ORM。你可以命名它的存储库,但实际上这将是一个ORM。

解决方案3反对仓库的想法,所以我建议不要使用它。在从数据库加载数据库的时刻以后,在提交期间,将它与当前状态进行比较,如何在工作单元中保存聚合的状态?你可以摆脱所有肮脏的标记的东西,但需要在内存中存储一​​些额外的数据。

1

解决方案1(使用脏标志)不合适,因为最终会导致持久性逻辑泄漏到您的域模型中。你的域模型不应该关心持久性:什么是变化的,什么是增加的,等等。

在Jimmy Nillson的书中,我注意到他处理这种情况的方式是每次聚合都要被持续,聚合根被更新,所有的子都被删除,然后再被插入。

这是一个相当简单的解决方案来实现,但它有一些影响。例如,每当您重新插入一个子对象时,其ID可能会改变。如果另一个用户同时编辑同一个聚合体会怎么样?

有没有其他人遇到过这个问题?

Mosh

+1

由于子实体不应具有全局身份,因此子对象的id可能会更改的事实不应该成为问题。 – thinkbeforecoding 2010-04-14 15:31:46

+0

请考虑这个例子:用户可能想要删除属于Order 1的OrderItem 11.这可以通过类似GetOrder(1).RemoveItem(11)的方法来实现。同时,另一个用户可能正在更新订单1.因此,重新插入订单1及其所有子项可能会导致OrderItems的ID被更改。因此,在这种情况下,OrderItem 11可能会变成OrderItem15。所以,对GetOrder(1).RemoveItem(11)的调用将失败。有什么我失踪?请澄清。 – Mosh 2010-04-16 02:07:27