在聚合根中搜索孩子

时间:2013-11-25 10:12:01

标签: c# domain-driven-design repository-pattern ddd-repositories aggregateroot

存储库模式表明您只能提取聚合根。但是,如果您不知道它的父(root),如何仅使用它的uniqiue身份(Child.ID)来检索单个孩子?

class Parent
{
    public int ID { get; set; }
    IEnumerable<Child> Children { get; private set; }
}

class Child
{
    public int ID { get; private set; }
    public virtual Parent Parent { get; private set; } // Navigational model
}

我的应用程序是无状态(web),为简单起见,请求只包含子项的ID。

我在考虑三种方法:

  1. 打电话给所有的父母,然后礼貌地问他们谁拥有这个孩子。
  2. 在ParentRepository中有一个名为get GetChildByID的特殊例程,它会使存储库的抽象失败。
  3. 修改请求以包含父级,但由于您已拥有唯一标识,因此似乎没有必要。

3 个答案:

答案 0 :(得分:2)

您可能真的在这里看到不同的有界背景。您在问题中提到&#34;存储库...只能提取聚合根。&#34; ;这是对的。另一个答案还提到,如果需要查询子对象,子对象也可能是聚合根。这也可能在不同的有界上下文中正确。实体很可能是一个上下文中的聚合根,另一个上是值实体。

Users的域名及其设备上已安装的移动设备/平板电脑Apps为例。在用户的上下文中,我们可能希望用户具有基本属性,例如姓名,年龄等,我们可能还需要用户在其设备上安装的应用列表。在此上下文中,User是聚合根,App是值对象。

bounded context UserApps
{
    aggregate root User
    {
        Id : Guid
        Name : string
        Age : int
        InstalledApps : App list
    }

    value object App
    {
        Id : Guid
        Name : string
        Publisher : string
        Category : enum
    }
}

在另一个背景下,我们可能会以App为中心观察世界,并确定App是聚合根。比如说我们想报告哪些用户安装了给定的应用程序。

bounded context AppUsers
{
    aggregate root App
    {
        Id : Guid
        Name : string
        InstalledBy : User list
    }

    value object User
    {
        Id : Guid
        Name : string
        InstalledOn : Date
    }
}

这两个有界上下文都有自己的存储库,它返回相应的聚合根。您对数据的看法存在微妙但重要的差异。

我认为如果您退后一步并考虑为什么您想要查询子对象,您可能会发现您实际上处于一个完全独立的有界环境中。

答案 1 :(得分:0)

如果您需要孩子进行显示/报告/查看/报告,则可以使用简单的查询图层。

如果你以任何方式操纵孩子,那么它就具有一致性边界,听起来很像聚合。

尽量不要查询域对象。另一个简单的经验法则不是在另一个聚合中包含聚合引用,而是仅使用引用的聚合的Id或甚至是表示关系的值对象。

答案 2 :(得分:0)

实体导航不是域模型的目的 聚合根是实体和值的组合,用于公开业务操作 作为副作用,您仍然可以通过AR执行一些简单的查询或导航,但是,对于复杂的查询,创建和使用查询模型更有效。
我在谈论CQRS

希望这可以帮到你。