0

我有以下课程:

class AggregateRoot
{
  // Defines common properties, Id, Version, etc.
}

class Container : AggregateRoot
{
  public IEnumerable<User> Users { get; }

  public void AddUser(User newUser)
  {
    // ...
  }

  // ...
}

class User
{
  public void AddNotification(Notification newNotification)
  {
    // ...
  }

  // ...
}

class Notification
{
  public string Message { get; set; }
}

如您所见,我有一个包含一个或多个用户的容器,每个用户可以有零个或多个通知发送给他们。

在这种情况下,最常见的操作是添加新通知,因此我会经常检索用户。从容器中获取用户是可能的,但是我需要检索容器对象并在用户集合中搜索。如果 Container 很小而且很新,这很好。但随着容器变老,它会获得更多用户。所以用户集合可以变得相当大。我的问题是 User 类是一个伪聚合根,很多操作都是在 User 上完成的,但是 User 不能存在于 Container 之外。使用存储用户的新存储库解决明显的性能问题带来了另一个问题。如何使用户存储库中的用户与容器中的用户保持同步?

我可以只将用户 ID 存储在 Container 类中,但这会带走将新用户添加到 Container 的业务逻辑,因为我不能再查找某些属性。那么,我该怎么做呢?

我正在使用 MongoDb 来存储事件。

4

1 回答 1

3

使用存储用户的新存储库解决明显的性能问题带来了另一个问题。如何使用户存储库中的用户与容器中的用户保持同步?

您可以以稍微不同的方式实现模型。如果唯一的行为Container是添加User实例,那么您也可以进行User聚合。为了表达用户必须是容器的一部分的约束,用户可以通过 ID 引用容器。

class User
{
  public int ContainerId { get; private set; }
  public void AddNotification() //...
}

Container 类仍然可以提供一些与添加用户相关的行为。例如,它可以提供一个用于创建新用户的工厂方法,该方法将由实现用例的应用程序服务使用:

class Container
{
  public int Id { get; private set; }
  public User CreateUser(string userName)
  {
    return new User(this.Id, userName);
  }
}

class UserAppService
{
  public void AddUserToContainer(int containerId, string userName)
  {
    var container = this.containerRepository.Get(containerId);    
    var user = container.CreateUser(userName);    
    this.userRepository.Add(user);
  }
}

在这个实现中,Container 不存储用户集合。之所以如此,是因为正如您所指出的,集合可能会变得非常大,因此无法在内存中进行管理。在 MongoDB 中,您将拥有一个容器集合和一个用户集合。

每当您遇到“伪聚合根”的概念时,您很可能有两个可能相关的聚合。这是解决此类问题的常用策略。有关该主题的深入处理,请查看Vaughn Vernon 的有效聚合设计

于 2012-10-15T17:33:14.630 回答