问题描述
我在 .NET Core 5 中使用 DDD 和 Onion 架构构建了一个 Web 应用程序。
有4层:
- 领域层 - 包含领域模型
- 应用层 - 具有核心业务逻辑并引用领域层
- 基础设施层 - 使用 EF Core 检索数据并将其保存到 Azure sql,它指的是应用层
- API 层 - 具有控制器并指应用程序和基础设施层
通过API层引用基础设施层只是为了连接数据库,任何对数据库的请求都会通过应用层;应用层具有在基础设施层实现的接口,用于保存和检索数据库中的数据。
现在,当我使用代码优先或数据库优先的方法创建数据库时,这些 EF 模型类应该去哪里?
将它们放在域层会破坏洋葱架构,因为域层不应该了解基础设施层的任何信息。
- 在领域层中放置模型和映射
我见过几个示例,其中模型和映射放置在域模型中,而这些映射用于基础结构层 OnModelCreating(..)
,但特定于数据库的基础结构层映射仍然存在于域层中。如果我想用其他数据库替换基础架构层,在这种情况下我需要更改对我来说似乎不合适的域模型,该怎么办..
- 在基础设施层放置模型
我可以在基础设施层放置 EF 模型类,但如何在应用层中引用它们?我是否需要为每个模型存储库提供一个接口,或者同一个接口是否存在多个依赖项注入?
我希望域模型由业务模型保存,并将 EF 模型放置在基础设施层,并在必要时使用 AutoMapper 在它们之间进行映射。
那么保存 EF 模型的最佳实践是什么,这样它就不会破坏 Onion 架构。
解决方法
好吧,您可以让基础设施层从 EF 核心检索数据并将其映射到域层,您必须为每个将返回域模型的存储库提供一个接口。对于同一接口的不同实现,您始终可以构建某种工厂来处理它。 类似 this 的答案。
,如果您使用的是 EF Core,我认为不需要单独的 EF 模型。
我通常做的是在领域层中实现领域模型类,以最好的方式支持我的业务逻辑。然后在基础设施层中放置实体框架配置类,使用带有泛型的IEntityTypeConfiguration。
这正是被认为是为了保持领域模型类不受基础设施问题的影响,这样即使您更改数据库实现,领域模型也永远不必更改。
您可以在由 Microsoft 提供支持的 EShopOnContainers 参考项目中看到一个工作示例 here。
例如,Order 聚合定义在域层中,而 EF Core 的相应模型 configuration class 放置在基础结构层中。
然后一切都像往常一样在 API project startup 和基础结构层的相应 DbContext (OrderingContext) 类中连接起来。
基础设施层将依赖于域层中的域实体,而不是相反,这是您希望在洋葱架构中实现的目标。