我已经设置了一个正在使用ORM填充的域项目。域包含不同的聚合,每个聚合都有自己的根对象。 我的问题是如何处理跨越聚合边界的属性?
一个例子:
上下文A =用户
背景B =游戏
在Users
上下文中有一个对象UserOwnedGames
。此对象具有属性User
,该属性是对同一Users
上下文中的对象的引用。该对象还具有Game
的属性,该属性显然不在用户中,而是在Games
上下文中。
这种关系会怎样(或应该?)?在数据库中很清楚(即2个外键),但代码应该是什么样的?
答案 0 :(得分:15)
听起来您的User
上下文也需要一个Game
实体。但请注意,这不一定是Game
上下文的根Game
实体。这两个有界的上下文可能对Game
是什么以及它具有什么属性有不同的看法。只有身份将两个游戏对象联系在一起。
User Context
{
Aggregate Root User
{
Identity;
Name;
OwnedGames : List of Game value entities
}
Value Entity Game
{
Identity;
Name;
}
}
Game Context
{
Aggregate Root Game
{
Identity;
Name;
Owner : User value entity
HighScore : int
TimesPlayed : int
... A whole bunch of other properties which are not relevant in the User context
}
Value Entity User
{
Identity;
Name;
// No OwnedGames property, in this context we don't care about what other games the user owns.
}
}
答案 1 :(得分:3)
您应该避免跨BC的数据库引用 - 您不应该尝试确保来自不同BC(事务)的聚合之间的引用完整性。理想情况下,交易应该只存在于单个聚合内部,甚至不是BC。
更好地使用ID的简单值对象 - UserId和GameId - 并在需要时将它们分配给实体。这样,这些“远程”实体完全分离,因此您不必担心它们的连接。可以使用消息传递平台实现同步。
如果你有空闲时间阅读这些有价值的文章(由Vaughn Vernon撰写):
答案 2 :(得分:1)
这取决于您使用的有限上下文策略。
如果您选择共享内核,我认为在它们之间建立直接关系(直接引用或标识符引用,我相信其他人将在其他答案中解释其优缺点)。并且您还提到了由数据库表集成的这些对象。
但是如果选择反腐败层,你最好将它们分开(只使用标识符来保持关系),使用适配器转换器进行集成(并且没有数据库集成)。