MVC DDD EF复杂子对象遍历

时间:2012-05-14 14:24:45

标签: asp.net-mvc entity-framework repository domain-driven-design

我正在讨论聚合根并使用导航属性遍历子对象。

情景1:

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

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

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

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

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

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

情景2:

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

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

现在因为我们查询了地址对象,这意味着我不必遍历客户对象就可以到达它。即使我使用客户存储库直接查询地址表并返回地址对象,这是否允许在关注DDD时?或者我应该使用方案1来查询客户存储库并返回客户对象,该客户对象是聚合根并遍历子对象?

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

只是想知道其他人如何在不降低性能的情况下彻底应用DDD,因为当您使用EF时会立即使用EF导航属性,然后会为每个子对象发送一个查询,如果它在一个for循环。

麦克

2 个答案:

答案 0 :(得分:1)

使用ER图来确定聚合时,您将无法走得太远:)

所有权不一定推断汇总。你只是指关系遍历。 Aggregate Roots是一项棘手的业务。我在我的网站http://www.ebenroux.co.za上发布了一些关于此内容的博客,您可能希望特别注意这一点:

Natural vs. Synthetic Aggregates

聚合具有明确的边界,需要特定的领域知识来确定边界的位置。之后就变成了所有权或弱参考。

答案 1 :(得分:1)

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

我在这个主题上看到的最有见地的事情之一是Effective Aggregate Design by Vaughn Vernon。我绝对建议给它一个阅读。他谈到的一件重要事情就是尽量让你的聚合体尽可能小。这自然会有助于提高绩效。

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

从DDD开始,我认为重要的是要提醒您仍然需要务实的设计选择; DDD并不能解决您的所有问题。在大多数情况下,设计选择是性能等方面的权衡。