0

我正在就聚合根和使用导航属性遍历子对象进行辩论。

场景一:

  • 客户是聚合根
  • 地址是一个实体
  • 联系人是一个实体

一个客户可以有多个地址,一个地址可以有多个联系人。我使用客户 ID 查询下面的客户存储库并返回一个客户对象。

Dim customer as Customer = _customerRepository.GetById(request.Id)

如果我们需要访问客户地址,我们将遍历客户对象中的地址,如下所示。

Dim address as Address = customer.RetrieveAddress(request.AddressId)

然后将针对 x 个子对象执行此方法。我展示的示例是一个简单的示例,但就包含数百万条记录的数据库表而言,一旦查询并返回聚合根对象,当遍历多个子对象时,其他人如何管理性能问题?

场景二:

与上面的示例相同,但我们不是查询客户存储库并返回客户对象,而是返回一个子对象。

Dim address as Address = _customerRepository.GetAddressById(request.AddressId)

现在因为我们已经查询了地址对象,这意味着我不必遍历客户对象来获取它。即使我已经使用客户存储库直接查询地址表并返回地址对象,在遵循 DDD 时是否允许这样做?或者我应该使用场景 1 来查询客户存储库并返回作为聚合根的客户对象并遍历子对象?

我问的原因是因为在我们的数据库图中,我们有几个表要从我们的聚合根遍历,并且随着时间的推移它可能包含数百万条记录,这会降低性能。

只是想知道其他人如何在不降低性能的情况下彻底应用 DDD,因为当您使用带有导航属性的 EF 时,一旦您使用它们,它就会为每个子对象发送一个查询,如果它处于 for 循环中,则可能发送 100 多个查询.

麦克风

4

2 回答 2

1

您将无法使用 ER 图来确定聚合:)

所有权并不一定意味着聚合。您只是指关系遍历。聚合根是一项棘手的业务。我在我的网站http://www.ebenroux.co.za上写了一些关于这个的博客,你可能特别想看看这个:

天然与合成骨料

聚合具有不同的边界,需要特定的领域知识来确定边界在哪里。之后就是简单地成为所有权或弱引用。

于 2012-05-14T15:04:36.013 回答
1

聚合是一项棘手的业务,决定聚合边界需要大量思考。阅读您的问题,我不太确定您是根据行为而不是数据库实体关系设计聚合。正如 Eben 所说,后一种方法不会走得太远,而且您的聚合最终可能会非常大(就子实体的数量而言)。

我读过的关于这个主题的最有见地的东西之一是Vaughn Vernon 的 Effective Aggregate Design。我肯定会推荐给它一个阅读。他谈到的一件重要的事情是试图使你的聚合尽可能小。这自然会对性能有所帮助。

对于子实体,我不会做你在场景 2 中所做的事情,因为你不应该通过聚合根来改变实体的状态;这保持了不变量。话虽如此,您的示例使用了一个可能是值对象的地址对象,因此出于性能原因有一个单独的地址存储就可以了。

When starting with DDD, I think its important to be reminded that you still need to be pragmatic with your design choices; DDD doesn't solve all your problems for you. In most cases the design choices are a trade-off for things like performance.

于 2012-05-15T08:48:10.810 回答