【问题标题】:Correct design of Repository->Service->Controller?Repository->Service->Controller的正确设计?
【发布时间】:2020-05-07 08:13:33
【问题描述】:

我想知道我是否在我的应用程序中使用了正确的架构。

在我的 API 中调用端点后,我目前正在执行以下流程: Api.EmployeeController.Update(Api.EmployeeUpdateDto) => Services.EmployeeService.Update(Service.EmployeeUpdateDto) => Data.EmployeeRepository.Update(Entities.Employee) => Data.EfDbContext.Employees.Update(Entities.Employee)

为了解释更多,我的 API 端点采用 Api.EmployeeUpdateDto,在控制器内它被映射到 Services.EmployeeUpdateDto 并传递给 Services.EmployeeService.Update()。 在 Services.EmployeeService.Update() 中,它通过 Id 检索实际的 db 实体并更新其值,然后将其传递给 EmployeeRepository.Update(),后者又调用底层 EF db 上下文。

由于某种原因,我的直觉告诉我它的层数太多了,我是不是漏掉了什么?

【问题讨论】:

    标签: .net architecture domain-driven-design repository-pattern


    【解决方案1】:

    好的。这些地方的步骤:

    1. Api.EmployeeController.Update(Api.EmployeeUpdateDto)
    2. Services.EmployeeService.Update(Service.EmployeeUpdateDto)
    3. Data.EmployeeRepository.Update(Entities.Employee)
    4. Data.EfDbContext.Employees.Update(Entities.Employee)

    首先。很高兴您有 EmployeeUpdateDto,因为您通常不会更新与创建新实体时完全相同的字段。但是,我通常会采用更多基于任务的方法,例如 LockUserDTORenameUserDTO 等,

    DDD 中有两种类型的服务。应用服务和领域服务。应用程序服务充当保护您的域的门面,而域服务用于协调多个实体之间的工作。

    Service.EmployeeUpdateDto 并没有真正增加任何价值。如果 API dto 发生变化,或者实体发生变化,它仍然需要更新。所以它没有提供任何进一步的抽象,只是拥有 API dto。所以我会去掉它,让应用服务直接使用 API dto。

    1. Api.EmployeeController.Update(Api.EmployeeUpdateDto)
    2. Services.EmployeeService.Update(Api.EmployeeUpdateDto)
    3. Data.EmployeeRepository.Update(Entities.Employee)
    4. Data.EfDbContext.Employees.Update(Entities.Employee)

    我通常避免将域实体用作数据库实体,因为它通常需要在设计中做出妥协,以便 ORM 可以正确地持久化它。请记住,领域实体是您最宝贵的财富。唯一应该推动他们的设计的是领域。

    【讨论】:

      【解决方案2】:

      是的,你把事情复杂化了,但这有点微妙。诀窍是存储库和服务层之间的层应该传入 EmployeeUpdateDTO,并且不应该知道有关实体的任何信息。该实体应包含在您的存储库层中。

      我不太清楚为什么你有一个 EmployeeUpdateDTO 而不仅仅是一个 EmployeeDTO,我只是将它简化为 EmployeeDTO,此时你有一个实际的域对象。

      这确实意味着您的服务层非常薄,这对于直接的 CRUD 操作是正常的。除非您正在做诸如使用更新日期之类的逻辑装饰 EmployeeDTO 之类的事情,否则它几乎是样板传递。

      Api.EmployeeController.Update(Api.EmployeeUpdateDto) => Services.EmployeeService.Update(Service.EmployeeDto) => Data.EmployeeRepository.Update(Service.EmployeeDto) => Data.EfDbContext.Employees.Update(Entities.Employee )

      【讨论】:

      • 只是想在这里补充一点,*Dto 要么是域对象的错误名称,要么没有。由于域是应用程序的核心,因此域对象应该是Employee。 UI 的表示应命名为 *Dto(因为大多数情况下它们实际上是通过网络传输的)。如果您有另一个持久性对象,那很好,但为域层保留业务名称(员工)
      猜你喜欢
      • 2011-01-06
      • 2017-01-21
      • 2023-02-02
      • 2021-09-02
      • 1970-01-01
      • 2011-09-08
      • 2013-03-09
      • 1970-01-01
      • 2015-06-21
      相关资源
      最近更新 更多