存储库模式表明您只能提取聚合根。但是,如果您不知道它的父(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。
我在考虑三种方法:
答案 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。
希望这可以帮到你。