如何聚合存储库?

时间:2012-10-16 14:51:43

标签: entity-framework domain-driven-design repository-pattern aggregate dbcontext

我正在为一家电信公司开发一个大型系统。我是DDD的新手,很难将不同的部分连接在一起。我们当前的系统是使用NHibernate构建的。它目前有超过600个表,所有数据访问都是使用NHibernate完成的,但对于新系统,我们将使用EF。以下是每个功能区域中的几个功能区域和数据库表的示例。

客户
    -----> CustomerDemographics
    -----> CustomerPayments
    -----> CustomerTransactions

RoutingEngine
    -----> InboundRoutes
    -----> OutboundRoutes

ProvisioningEngine
    -----> InboundSwithces
    -----> OutboundSwitches
    -----> RouterConfigs
    -----> GatewayConfigs

BillingEngine
    -----> InboundTraffic
    -----> OutboundTraffic

由于系统必须是可单元测试的,我开始使用存储库模式抽象实际实体。一种方法是为每个数据库表创建一个存储库对象。当然,所有这些存储库类都可以从通用存储库接口派生。然而,这将在代码库维护方面增加相当多的开销。在DDD中,我读到了聚合这个概念,但我不确定它应该如何在EF的上下文中特别应用。 Aggregate对象应该是这些存储库的容器还是更多是相关上下文的容器(意味着有界DbContexts的内容)?

2 个答案:

答案 0 :(得分:6)

  

一种方法是为每个数据库创建一个存储库对象   表

在DDD中,由于持久性无知的概念,数据库表通常不与存储库进行一对一映射。相反,存储库应该与聚合一对一。

  

当然,所有这些存储库类都可以从泛型中派生   存储库接口。

存储库模式可能是一个滑坡。虽然它非常适合封装,但很容易被不必要的抽象带走。看看here以获得另一种观点。

  

Aggregate对象应该是这些存储库的容器还是   这些更像是相关语境的容器(意思是某种东西   沿着有界DbContexts的路线?)

似乎所谓的“功能区域”在DDD中称为bounded contexts(BC)。 (不是EF中的DbContext)。此外,聚合不是存储库的容器,它们包含域模型中的一组相关实体。定型示例是销售订单模型,其中您有订单聚合,其由订单聚合根和各种实体以及订单行项等值对象组成。如上所述,聚合是存储库应提供访问权限的域对象。因此,您应该围绕聚合构建存储库,但当然首先必须识别聚合和BC。看看Effective Aggregate Design by Vaughn Vernon

此外,在单个BC中拥有600个桌子似乎太多了,这是一个潜在的迹象,表明你有多个BC正在发挥作用。 BCs实现的是functional cohesion,这反过来最适合与您的存储库进行分组(“汇总”与DDD术语的冲突)。

答案 1 :(得分:2)

DDD中的聚合是一致性边界 - 事务一致性的岛屿。如果域模型中的对象集群应该保持事务一致性并且可以被视为有意义的概念整体,那么您可能有一个聚合。在聚合中,您可以获得最终的一致性。

如果您正在进行新的开发,我建议您首先在对象中建模您的域,然后计算出数据库架构应该作为后续传递的内容。

我建议将一个庞大的模型分解为许多更专业的领域模型,可能沿着功能领域的广泛范围,仔细注意每个模型要处理的关键业务方案(即您要解决的业务问题是什么)每个型号)。每个模型都需要有一个良好的边界(即它应该在明确定义的有界上下文中),其中很清楚什么属于一个模型,什么属于另一个模型。这通常通过将模型边界与某种子系统边界(在架构上)对齐来实现。