DDD-如何在EF Core中跨边界上下文管理实体



我还没有找到具体的例子。我知道每个有界上下文都有自己版本的实体,不应该在上下文之间共享实体。但是,在使用类似于ORM的EF时,我该如何处理这一问题呢?

例如,以下是我的实体和它们存在的有界上下文:

成分(实体有界上下文A)

Recipe(实体有界上下文b)
Ingredient(实体有缘上下文b)
MenuItem(聚合有界上下文b)

现在,每个有界上下文都将有自己版本的成分。但既然EF中有一个单独的DB上下文来管理它,我该如何安排呢?我正在使用CQRS,以便在需要时触发事件。我的计划是在我的Recipe实体中维护一个id列表,并从数据库中提取相关的配料,这样数据就不会重复。

但我不确定我对数据重复的担忧是否有效。在我上面的例子中,想象一家企业出售食材,但也有预设的食谱(带有食材列表),可以在食品摊上出售。

在一种情况下,成分与另一个实体没有关系,而在另一种情况中,它是一个子实体(在聚合中)。我可以看到它应该如何设计(在有界的上下文中分离实体),但当涉及到DB时,它实际上是如何设置的?如果在上下文A和上下文B中需要跟踪的成分的性质/领域知识不同,该怎么办?这会变成一张单独的桌子吗?我对此有点不知所措。

编辑:请记住,我在这里只使用了一个数据库。我知道通常每个有界上下文都有单独的DB来避免这种情况,但我想知道如何通过1个DB来实现这一点。

我将把你的问题分为两部分:

  1. 架构部分:有边界的上下文设计/边界
  2. 技术部分:数据库模式管理、EF映射等

从第1点开始,我要强调的是,有界上下文的边界比你在问题中暗示的要厚。如果边界定义得很好,BC之间几乎没有数据重复,部分来自一些Id,而不是更多。在您的情况下,BC-A中的成分与BC-B中的成分具有相同的Id。

例如,你的BC-A可能会从成分中管理名称、描述、图片等。BC-B不需要这些信息,但它可能具有创建配方所需的一些重要特性。以类似的方式,BC-C可能有每种成分的供应商、价格等。

此外,在你的BC-B中,你可能有两个地方的成分:一个表,里面有所有成分及其有趣的特性,作为配方的一部分,作为实体。例如,这个实体不会具有所有这些属性,而是具有配料Id加上配方中使用的数量。

有了这种类型的设置,不仅在原则上不希望,而且在实践中也不希望在有边界的上下文中共享Ingredients表。

很多时候,数据复制的需求来自于用户界面的需求。例如,当您显示Recipes时,您需要显示Ingredient的名称,但这可以通过UI合成来解决。UI可以从BC-B中提取配方,并使用BC-A中的名称以及BC-C中的价格来丰富数据。

如果你遵循这种方法,第2点应该是独立的:每个BC都应该有自己的DbContext。对所有DbContext使用相同的连接字符串(数据库)是可以的,但您可以使用特定的DB模式初始化DbContext。这样,您可以在每个BC中都有一个Ingredients表,而不会发生DB表冲突,并且每个DbContext也可以有EF迁移版本表(尽管我相信它也适用于共享表)。这种设置还为您提供了一个优势,即允许您在每个有界上下文的单个DB中分离数据库,而无需更改任何代码。出于可扩展性的原因,或者为了促进基础设施作为代码等,您可能最终需要这样做。

TL/DR:只要数据不共享,拥有一个数据库服务是完全可以的(对于较小的服务或由于某些特定业务的原因)。如果你使用普通形式的数据库,请使用不同的表来存储你的两种成分。

更长版本:

如果在这两个有界上下文中的ingredient实体由同一个物理支持,并且它们可以共享数据(一个Ingredient实体可以对另一个Ingient实体创建的数据进行操作),那么它们并不是真正独立的。

将BC作为边界的一个非常重要的方面是,准确地允许这些实体独立进化。通过让它们共享一个表(或文档集合),您不会允许这种情况发生。此外,这违反了更通用的(我指的是非DDD特定的)准则"你不应该跨越服务边界共享数据库"。

最新更新