简体   繁体   English

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

[英]DDD - How to manage entities across bounded contexts in EF Core

I have not found concrete examples of this.我还没有找到具体的例子。 I know that each bounded context has its own versions of entities and you should not share entities across contexts.我知道每个有界上下文都有自己的实体版本,您不应该跨上下文共享实体。 But how do I manage this in relation to using an ORM like EF?但是我如何管理与使用像 EF 这样的 ORM 相关的问题?

For example, below are my entities and bounded contexts they exist in:例如,下面是我的实体和它们存在的有界上下文:

Ingredient (entity bounded context A)成分(实体有界上下文 A)

Recipe (entity bounded context b)配方(实体有界上下文 b)
Ingredient (entity bounded context b)成分(实体有界上下文 b)
MenuItem (aggregate bounded context b) MenuItem(聚合有界上下文 b)

Now each bounded context will have its own version of ingredient.现在每个有界上下文都有自己的成分版本。 But since I have a singular DB context in EF for managing this, how exactly do I arrange this?但是由于我在 EF 中有一个单一的数据库上下文来管理这个,我究竟该如何安排呢? I am using CQRS so I can trigger events if needed.我正在使用 CQRS,因此我可以在需要时触发事件。 My plan was to maintain a list of ids in my Recipe entity and pull in the relevant Ingredients from the database so that data is not duplicated.我的计划是在我的 Recipe 实体中维护一个 id 列表,并从数据库中提取相关的成分,以便数据不会重复。

But I'm not sure if my data duplication concern is valid.但我不确定我的数据重复问题是否有效。 In my example above, imagine a business which sells ingredients but also has preset recipes (with a list of ingredients) that it can sell in a food stall.在我上面的例子中,假设一家企业销售原料,但也有可以在食品摊位出售的预设食谱(带有原料清单)。

In one context, ingredients has no relation to another entity while in another context its a child entity (in an aggregate).在一个上下文中,成分与另一个实体没有关系,而在另一个上下文中它是一个子实体(在聚合中)。 I can see how it should be designed (separate entities in bounded contexts) but when it comes to the DB, how is this actually setup?我可以看到它应该如何设计(有界上下文中的单独实体)但是当涉及到数据库时,这实际上是如何设置的? What if the properties/domain knowledge that need to be tracked in context A vs context B for ingredients is different?如果需要在上下文 A 和上下文 B 中跟踪成分的属性/领域知识不同怎么办? Will this end up being a separate table?这最终会成为一个单独的表吗? I'm a bit lost on this.我有点迷失了。

Edit: Please keep in mind I'm only using 1 database here.编辑:请记住,我在这里只使用了 1 个数据库。 I understand that usually you have separate DB per bounded context to avoid this scenario but was wondering how this can be accomplished via 1 DB.我知道通常每个有界上下文都有单独的 DB 以避免这种情况,但想知道如何通过 1 DB 来实现这一点。

I would separate your question in two parts:我将您的问题分为两部分:

  1. An architectural part: Bounded context design/boundaries架构部分:有界上下文设计/边界
  2. A technological part: Database schema management, EF mapping, etc技术部分:数据库模式管理、EF映射等

From point 1, I would stress that the Bounded Context boundaries are thicker than what you imply in your question.从第 1 点开始,我要强调的是,有界上下文边界比您在问题中暗示的要厚。 If boundaries are well defined, there is little data duplication between BCs, a part from some Ids and little more.如果边界明确定义,那么 BC 之间几乎没有数据重复,一些 Id 的一部分等等。 In your case, the ingredients in BC-A have the same Ids than the ingredients in BC-B.在您的情况下,BC-A 中的成分与 BC-B 中的成分具有相同的 ID。

For example, your BC-A might manage the name, description, pictures and so on from the ingredients.例如,您的 BC-A 可能会管理成分的名称、描述、图片等。 BC-B does not need this information, but instead, it might have some important properties required in order to create the recipes. BC-B 不需要此信息,但它可能具有创建配方所需的一些重要属性。 In a similar way, a BC-C might have the providers, prices and so on of every ingredient.以类似的方式,BC-C 可能包含每种成分的供应商、价格等。

Also, in your BC-B, you might have the ingredients in two places: A table with all the ingredients and their interesting properties for the recipes and as Entities as part of a Recipe.此外,在您的 BC-B 中,您可能将成分放在两个位置:一张包含所有成分及其有趣属性的表格,以及作为食谱一部分的实体。 This entity wouldn't have all those properties, instead it would have the Ingredient Id plus the quantity used in that recipe, for example.例如,该实体不会具有所有这些属性,而是具有成分 ID 加上该配方中使用的数量。

With this type of set up, it's not only non desirable in principle, but even in practice, to share the Ingredients tables across Bounded Contexts.使用这种类型的设置,不仅在原则上是不可取的,甚至在实践中,跨限界上下文共享成分表也是不可取的。

Many times, the need from data duplication comes from UI needs.很多时候,数据复制的需求来自UI需求。 For example, you will need to show the Ingredient's names when you show Recipes, but this can be solved by UI composition.例如,当您显示 Recipes 时,您将需要显示 Ingredient 的名称,但这可以通过 UI 组合来解决。 The UI can pull the recipes from BC-B and enrich the data with the names in BC-A and maybe with the prices in BC-C. UI 可以从 BC-B 中提取食谱,并使用 BC-A 中的名称以及 BC-C 中的价格丰富数据。

If you follow this approach, point 2 should fall on its own: every BC should have its own DbContext.如果您遵循这种方法,则第 2 点应该是独立的:每个 BC 都应该有自己的 DbContext。 It is OK to use the same connection string (database) for all DbContext, but you can initialize the DbContext with specific DB schema.可以对所有 DbContext 使用相同的连接字符串(数据库),但您可以使用特定的 DB 模式初始化 DbContext。 This way, you can have an Ingredients table in each BC without DB table conflicts and you can have EF migrations versions tables per DbContext as well (although I believe it also works with a shared table).这样,您可以在每个 BC 中拥有一个成分表而不会发生 DB 表冲突,并且您也可以为每个 DbContext 拥有 EF 迁移版本表(尽管我相信它也适用于共享表)。 This set up also gives you the advantage of allowing you to separate the databases in a single DB per Bounded Context without having to change any code.此设置还为您提供了一个优势,即允许您将每个有界上下文的单个数据库中的数据库分开,而无需更改任何代码。 You might need this eventually for scalability reasons, or to facilitate infrastructure as code, etc.出于可扩展性的原因,或者为了促进基础设施即代码等,您最终可能需要它。

TL/DR: having a single db service is perfectly OK (for smaller services or due to some bussiness specific reason), so long as the data aren't shared . TL/DR:拥有单个 db 服务是完全可以的(对于较小的服务或由于某些特定于业务的原因),只要数据不共享 If you use a normal form db, use different tables to store your two ingredients.如果您使用正常形式的数据库,请使用不同的表来存储您的两种成分。

Longer version:更长的版本:

If your ingredient entities in those two bounded contexts are backed by the same physical table , and moreover they can share data (one Ingredient entity can operate on data created by the other ingredient entity), then they're not really independent.如果这两个有界上下文中的ingredient实体由同一个物理表支持,而且它们可以共享数据(一个成分实体可以对另一个成分实体创建的数据进行操作),那么它们就不是真正独立的。

One very important aspect of having BC as a boundary, is to exactly allow those entities to evolve independently.以 BC 作为边界的一个非常重要的方面是准确地允许这些实体独立发展。 By having them share a table (or document collection), you don't allow for that to happen.通过让他们共享一个表(或文档集合),您不允许这种情况发生。 Moreover, this is violating the more generic (I mean non-DDD specific) guideline of "you shouldn't share a db across service boundaries".此外,这违反了“您不应跨服务边界共享数据库”的更通用(我的意思是非 DDD 特定的)准则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM