聚合,事务一致性和实体框架DbContext

时间:2015-02-22 13:47:09

标签: domain-driven-design ddd-repositories

聚合必须设计为事务性和最终一致性。实体周围的这种一致性边界有助于管理复杂性。

在我们的存储库实现中,我们使用Entity Framework与实际数据库进行交互。从历史上看,我们总是拥有巨大的上下文(跨越数十个表),它们代表数据库中的每个可用表,字段和关系(或者至少在数据库的某个功能区域中)。这里的问题是,这个上下文用于数百种不同的事物,并随着系统变大而呈指数级增长,从而导致难以维护的事物。

按有界上下文划分

由于这个原因,通常建议为系统中的每个有界上下文创建单独的DbContexts。 Julie Lerman在她的文章Shrink EF Models with DDD Bounded Contexts中提出了这一点。

按聚合划分

如果我们的聚合在事务上是一致的,那么是什么阻止我们更进一步并创建专用上下文来为每个聚合存储库提供服务?

不是混杂(服务于每个人的需要),而是提供上下文 明确的意图

  • 只有在需要更改聚合时才需要更改上下文。它随着聚合而演变。对于更大的上下文,系统的许多部分可能依赖于上下文的一部分。一次改变可能会危及很多。

  • 只需要在上下文中存在聚合所需的表,字段和关系。通常在处理更大的上下文时,您不会对给定表上的大多数关系或字段感到困扰。

这种方法存在缺陷。即:

  • 虽然它们可能会以不同方式建模(取决于它们的用途),但某些数据库表和关系可能需要存在于多个上下文中。

  • 如果使用,代码优先迁移将会非常棘手。

  • 这可能被视为过度工程。

任何人都可以提供有关此方法的进一步见解吗?是否有一些我忽略的内容?

修改

请注意,我们未在域中使用EF数据实体。我们的存储库从这些数据实体中实例化并融合了更丰富的域模型。

3 个答案:

答案 0 :(得分:2)

我没有看到多重聚合上下文是一个问题,特别是如果你遵循严格的聚合分离 - 没有引用聚合之外的实体,只有按键的根到根松散引用。

另一方面,如果您确定它是性能瓶颈,我可以理解为什么您会想要原子DbContexts。

但有一件事:EF上下文不必完全映射到Domain layer Bounded Contexts。如果他们这样做并且您尝试尽可能地缩小双方的上下文,则可能会导致域层IMO受损。域名BC可能会失去一致性,重要的无处不在的语言概念和细分的语义可能会在此过程中丢失。

答案 1 :(得分:1)

好问题 - 如果您使用EF作为CRUD访问来实现存储库然后在顶级富DDD实体上进行分层,那么您的有界上下文将决定用于保留所有实体的基础数据库模式的大小包含在?

如果基础表和EF上下文很大,我认为这表明有限的上下文可能被进一步分解?

我在EF找到了一个有用的链接:http://mehdi.me/ambient-dbcontext-in-ef6/当我开始使用非常复杂的EF模式时,我尝试了不同的技巧,但最终将它们换成了EventSourcing存储库,但只是在预测和基础设施的痛苦是值得远离迁移,表耦合等。

最终,如果建模的有界上下文的大小正确,那么即使所有DbSets都包含在同一个DbContext中,复杂性仍然是可管理的。

我的建议是通过坚持使用较小的有界上下文而不是在有界上下文之间共享EF上下文/数据库来保持一切正常和可管理。

您可能会发现,当有界上下文被重新分解并拆分时,您可以将某些部分建模为直接使用EF的纯CRUD访问直接使用EF作为ORM直接指向POCO然后直到您的应用程序层。

答案 2 :(得分:0)

  

如果我们的聚合在事务上是一致的,那么是什么阻止我们更进一步并创建专用上下文来为每个聚合存储库提供服务?

在我看来,这是一个非常糟糕的主意。让我给你一些见解。

在Domain Driven Design中,您有两种工具;战略和战术。你不应该根据任意战术解决方案划分你的模型

Bounded Context是一种战略工具。这为创建特定业务问题域的解决方案提供了建模边界。在单个有界上下文中是由团队制定的Ubiquitous Language。在一个signel建模边界中,团队可以使用任意数量的有用的战术建模工具,例如AggregatesEntitiesValues Objects

因此,应用DDD的最大值符合Bounded Contexts的正确定义。这不仅仅是一个理论上的神器。 按汇总划分会导致混乱和混乱。您将无法清楚地说明您正在解决的域名问题。

另一方面,您只能使用AggregatesEntitiesValues Objects等战术模式,但这不是域驱动设计。

  

而不是滥交(满足每个人的需要),它会给上下文明确的意图......

怎么样?我无法得到它。对我来说,它会造成更多混乱。有界上下文集成通过Anti corruption layers完成,可以保护您免受外部变更的影响。有界背景可以独立于其他环境而发展。如果您想更多地了解有限上下文之间的集成是如何从策略角度出发的,请查看Context mapping

  

虽然它们可能会以不同的方式建模(取决于它们的用途),但某些数据库表和关系可能需要存在于多个上下文中。如果使用,代码优先迁移将是棘手的。这可能被视为过度工程。

在进行域驱动设计时,您不会根据技术限制来推动您的选择,尤其是ORM框架。

更进一步:

聚合有时可以与Bounded Context进行1:1映射。但这实际上取决于业务问题而非技术解决方案。

如果没有更深入的了解,域驱动设计就不容易应用。有时你的域名并不真正需要它,所以没有必要试图强迫它解决你的具体问题。

作为结论,我会坚持Julie Lermann的文章中提出的命题。