何时将DTO映射回其实体对应物是否合适

agg*_*ech 7 domain-driven-design dto

从我所阅读和实现的内容来看,DTO是从Data模型中保存值子集的对象,在大多数情况下,它们是不可变对象.

我需要传递新值还是更改回数据库的情况怎么样?

我应该直接使用我的表达层中的DAL中的数据模型/实际实体吗?

或者我应该创建一个可以从表示层传递到业​​务层的DTO,然后将其转换为实体,然后通过ORM调用在DB中进行更新.这写的代码太多了吗?我假设如果表示层没有数据模型的概念,则需要这样做.如果我们采用这种方法,我应该在提交更改之前在BLL层再次获取对象吗?

gui*_*e31 20

一些想法:

  • DTO是一个加载术语,但由于它代表数据传输对象,我将其视为一个纯技术的,可能可序列化的容器,可以将数据从一个点传递到另一个点,通常是跨层或可能是层.在处理业务问题的层中,例如DDD中的Domain层,这些流通的小数据结构往往被命名为Value Objects,因为它们具有商业意义并且是域的泛在语言的一部分.DTO和Value Objects之间存在各种细微差别,例如您通常不需要比较DTO,而比较和相等是VO中的一个重要问题(如果它们的封装数据相等,则两个VO是相等的).

  • DDD强调丰富域模型的思想.这意味着您通常不会简单地将DTO的一对一映射到域实体,而是尝试将业务操作建模为实体中的意图揭示方法.例如,你不会用setter方法来修改UserStreet,City并且ZipCode而是调用一个moveTo(Address newAddress)方法来代替,Address是在域层声明的值对象.

  • DTO通常不会到达Domain层,而是通过Application层的过滤器.它可以是控制器或专用的应用程序服务.它的应用层对象知道如何将从客户端获得的DTO转换为对域层实体(通常是从存储库加载的聚合根)的正确调用.上面的另一个改进是构建基于任务的UI,其中用户不发送以数据为中心的DTO,而是发送反映其最终目标的命令.

因此,将DTO映射到实体并不是DDD的实际操作方式,它更多地表示面向CRUD的方法.


Yor*_*rro 6

我应该直接使用表示层中 DAL 中的数据模型/实际实体吗?

这对于中小型项目来说是可以的。但是,当您的大型项目有超过 5 名开发人员,其中不同的层分配给不同的团队时,那么使用 DTO 将数据层与表示层分开,该项目就会受益。

中间有 DTO,表示层的任何更改都不会影响数据层(反之亦然)

或者我应该创建一个可以从表示层传递到业​​务层的 DTO,然后将其转换为实体,然后通过 ORM 调用在数据库中进行更新。这样写代码是不是太多了?我假设如果表示层没有数据模型的概念,那么这是需要的。如果我们采用这种方法,我是否应该在提交更改之前在 BLL 层再次获取对象?

对于创建新实体,这是通常的方法(例如“新用户”)。为了更新现有实体,您不需要将 DTO 转换为实体,而是获取现有实体,映射新值,然后启动 ORM 更新。

UpdateUser(UserDto userDto)
{
    // Fetch
    User user = userRepository.GetById(userDto.ID);

    // Map
    user.FirstName = userDTO.FirstName;
    user.LastName = userDTO.LastName;

    // ORM Update
    userRepository.Update(user);
    userRepository.Commit();
}
Run Code Online (Sandbox Code Playgroud)

对于拥有许多开发人员的大型项目来说,编写过多代码的缺点与其提供的解耦的巨大优势相比是微乎其微的。

请参阅我关于为什么使用 DTO 的文章

  • “为了更新现有实体,您不会将 DTO 转换为实体,而是获取现有实体,映射新值”您难道不会以这种方式编写两次相同的映射代码吗? (2认同)