关于表达与References和Repositories的关系的一些令人困惑的事情

时间:2013-02-06 18:48:16

标签: domain-driven-design

•我们可以通过对象引用在两个实体之间表达关联(尽管聚合根与其内部实体之间存在关系) 也可以通过在根 - > SomeRootEnt.BorrowMeIntEnt(...))或存储库上定义的方法表示,它将检索相关来自数据库的实体
•当通过存储库表达关系时,客户端将直接调用存储库以获取相关实体 <登记/> •关于如何表达关系的决定取决于维护完整性是否需要此关系(也许是行为要求关联能够表达自己)

1)如果通过 Repository 表达 relationship (比如 1:* ),则需要子实体包含父实体的 ID (注意:这个问题假设至少一个父是一个根或者它们都在同一个聚合中)?

2)不同聚合中实体之间的关系 只能用 ID

表示

a)为什么?

b)这样的关系基本上不会通过 Repository 来表达吗?

c)如果 b)为“是”,则表明大多数情况下实体在不同聚合之间的关联不是必需的为了支持特定的行为?如果是,为什么?

更新

2a)

  

表达与身份参考的关系不同于   表达与对象引用的关系。原因   这种关系应以身份来表达,以维持   事务完整性 - 即只修改一个聚合   在任何给定的交易中。如果使用了对象引用,则为两个   聚合可能会受到交易的影响。

我 - 我理解你要做的一点,因为如果用对象引用表示关系,那么只是因为聚合A1(正在被修改)是“物理上“连接到另一个聚合A2,它意味着A1的一个部分(即A2&lt; - 实际上A2实际上不是A1的一部分,但希望你理解这一点)与其他部分不同步?”

II - 但从概念上讲,如果我们修改A1,那么即使两者之间的关系没有用对象引用表示,这两个聚合仍然不同步,所以实际上, A1和A2是否物理连接有什么区别?

III - 无论如何,为什么我们在两种情况下都不能简单地使用最终的一致性

第二次更新:

original_2)

  

要明确,根实体(AR)之间的关系应该是   以身份表达。非根实体之间的引用   应该禁止使用不同的聚合。

我们是否可以只从 A1非根实体 A2根实体(即非根实体)遍历单向关联在A1中将包含A2根ID?

2) a)

  

如果使用了对象引用,则两个聚合可能会受到a的影响   事务。

     

它创造了A2在交易中被修改的可能性   正在修改A1。通过标识引用A2消除了这一点   可能性。此外,数据库锁定等内容不适用于A2   加载A1时。

暂时忽略在更新A1时DB锁定不适用于A2的事实 - 为什么我们在某些情况下不允许在单个事务中修改A1和A2?

我知道聚合定义了一致性边界,但是如果在极少数情况下我们需要在同一个事务中同步A1和A2,那么只有其他替代方法可以将A1和A2转换为单个聚合,在该特定模型中可能不合适?!

谢谢

1 个答案:

答案 0 :(得分:1)

1)是的。例如,假设您有一个订单客户。要获得客户的所有订单,您可以通过订单存储库选择具有相应CustomerId的所有订单。

2)要明确的是,根实体(AR)之间的关系应该用身份来表达。应禁止在不同聚合中的非根实体之间的引用。

2a)表达与身份参考的关系不同于表达与对象参考的关系。关系应该用身份表达的原因是为了保持事务完整性 - 即在任何给定的事务中只修改一个聚合。如果使用了对象引用,则两个聚合可能会受到事务的影响。

2b)是的。存储库允许遍历和身份表达关系。

2c)这是聚合的全部要点 - 它应该定义一致性边界。如果对聚合的更改应该影响聚合,那么这些更改应该能够以最终一致的方式应用。

<强>更新

2a1)它创建了在修改A1的事务中修改A2的可能性。通过身份引用A2消除了这种可能性。此外,加载A1时,数据库锁定等内容不适用于A2。

2a2)如果修改A1的事务导致需要应用于A2的更改,那么这些更改将最终同步。保持它们物理分离的原因在2a1中说明。

2a3)你可以,但同样,2a1中指出的原因解释了为什么最好使用身份引用。

更新2

2)我想如果保持两个AR的完整性并且参考使生活更容易,那么它是可以接受的。引用本身不是问题,它可能导致问题。

2a1)其中一个原因是植根于更现代的文档数据库体系结构。文档数据库通常仅支持单个文档上的原子事务。另一个原因是两个AR可以存储在不同的数据库中,在这种情况下,需要分布式事务来保持一致性。但是,关系数据库当然可以锁定多个表,因此可以在事务中修改两个AR。因此,这些约束应被理解为指导方针。如果理解了所有分支并且使用了警告,那么更新两个AR是可以接受的。