实现有界上下文时优化数据库查询

3
在我们的项目中,我们试图应用分界上下文理念,但我们面临性能方面比较明显的问题。例如,在系统中,我们有不同的类(在不同的上下文中)用于表示用户:在核心域上下文中为Person,在安全上下文中为User。因此,我们为每个聚合拥有两个不同的存储库,但它们使用相同的数据库表,并且有时访问相同的数据。

在这种情况下,是否有通用的解决方案来最小化数据库往返次数?是否有ORM可以处理它,或者我们应该自己编写缓存系统?

更新:数据库来自旧应用程序,并且我们必须按照原样使用它。

2个回答

3
所以,我们为每个聚合定义了两个不同的存储库,但它们在数据库中使用相同的表,并且有时访问相同的数据。
您在同一张表中存储两个聚合的事实表明设计存在问题。在这种情况下,似乎您有两个有界上下文 - 一个用于核心领域(人在此处),另一个用于身份验证/访问(用户在此处)。这些有界上下文是相关的,后者可以被视为前者的上游。核心领域中的“人”对应于身份验证 BC 中的“用户”,但它们并不完全相同。
除了有关 BC 之间关系的这些问题外,还涉及到行为所有权的问题。例如,一个人和一个用户都可能有一个名字,需要确定的是谁拥有更改名称的行为。这可以通过几种方式实现。人可以拥有自己的姓名,并且更改应该传播到身份验证 BC。同样,用户可能拥有更改姓名的权利,在这种情况下,必须通过同步机制将更改传播到人。

总的来说,您的问题可以通过两种方式解决。首先,您可以将Person和User聚合存储在不同的表中。任何给定的查询都应仅使用其中一个表,并且它们可以以最终一致的方式进行同步。另一种方法是将行为域模型与用于查询的模型(read-model)分离。这样,您可以创建一个专门为特定屏幕设计的读取模型,并具有自定义查询,甚至可能在ORM之外。


我忘记提到数据库来自遗留应用程序,因此我们必须 "按原样" 使用它。谢谢您的回复,我会查看您提供的文章。 - vorou
1
“在同一张表中存储两个聚合根的事实表明设计存在问题。”在领域驱动设计中,设计应该完全不知道数据库模式,因此很难看出数据库如何对设计产生影响。“另一种方法是将行为领域模型与查询模型(读模型)分离。”这是非常好的建议,点赞! - MattDavey
如果模式保持不变,那么我仍然会有单独的存储库。这样,至少您的代码将被组织起来。如果必须从同一张表中选择两次,那就这样吧。总体而言,性能损失可以忽略不计。 - eulerfx

1
如果所有用户也都是人(有时外部服务也被建模为特殊的用户),那么用户和人应该在数据库中共享的唯一数据只有它们的标识符。事实上,领域模型中的每个实体都应仅包含对确保其不变式所需的数据的引用。
此外,我猜用户是由用户名来识别的,而人则是由其他东西来识别(增值税代码或类似东西)。因此,最简单的优化技术是避免封装与实体的不变性无关的信息
此外,您只需要一个有效的上下文映射技术,以便在需要时轻松从用户转到人。我使用共享标识符来实现这一点。
例如,您可以在用户类中公开人的标识符,这样对人的存储库进行简单查询即可提供您所需的数据。
最后,我建议您参阅Vaughn Vernon关于聚合根设计系列

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接