Asp.net mvc MVC DDD EF复杂子对象遍历

Asp.net mvc MVC DDD EF复杂子对象遍历,asp.net-mvc,entity-framework,repository,domain-driven-design,Asp.net Mvc,Entity Framework,Repository,Domain Driven Design,我正在讨论聚合根,并使用导航属性遍历子对象 情景1: 客户是聚合根 地址是一个实体 联系人是一个实体 一个客户可以有多个地址,一个地址可以有多个联系人。我使用客户Id查询下面的客户存储库,并返回一个客户对象 Dim customer as Customer = _customerRepository.GetById(request.Id) 如果我们需要访问客户地址,我们将遍历客户对象中的地址,如下所示 Dim address as Address = customer.RetrieveAd

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

情景1:

  • 客户是聚合根
  • 地址是一个实体
  • 联系人是一个实体
一个客户可以有多个地址,一个地址可以有多个联系人。我使用客户Id查询下面的客户存储库,并返回一个客户对象

Dim customer as Customer = _customerRepository.GetById(request.Id)
如果我们需要访问客户地址,我们将遍历客户对象中的地址,如下所示

Dim address as Address = customer.RetrieveAddress(request.AddressId)
然后,将对x个子对象执行此方法。我所展示的示例很简单,但就包含数百万条记录的DB表而言,在查询并返回聚合根对象后,其他人在遍历多个子对象时如何处理性能问题

情景2:

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

Dim address as Address = _customerRepository.GetAddressById(request.AddressId)
现在,因为我们已经查询了address对象,这意味着我不必遍历customer对象来访问它。即使我使用客户存储库直接查询地址表并返回地址对象,但在遵循DDD时是否允许这样做?或者我应该使用场景1查询客户存储库并返回作为聚合根的customer对象并遍历子对象

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

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


Mike

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

所有权不一定意味着聚合。您只是指关系遍历。聚合根是一件棘手的事情。我在我的网站上写了一些关于这一点的博客,您可能想特别关注这一点:


聚合具有独特的边界,需要特定的领域知识来确定该边界的位置。在这之后,它就变成了所有权或弱引用。

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

关于这个话题,我读到的最有见地的东西之一是。我绝对建议你读一读。他谈到的一件重要的事情是尽量使你的集合尽可能小。这自然有助于提高性能

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

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