跳到主要内容
版本:3.0.0

Dto 数据传输层

这一层只做传输,不做别的。

平时按这条记就够:

  • API 入参用 XxxRequest
  • 传输对象用 XxxDto

这一层一般放什么

最常见的就是两类:

  • Requests
  • Dtos

如果业务域多,就在它们下面继续按领域拆目录。

Dto 怎么写

Dto 是传输对象,不是数据库实体。

这一层通常会放:

  • 详情对象,例如 UserDto
  • 列表对象,例如 UserListDto
  • 聚合对象,例如 PatientInfoAggregateDto

写的时候守住三条就够:

  • 不带数据库痕迹
  • 不写业务逻辑
  • 只负责把数据传出去

像下面这些数据库字段,没有特殊理由就不要直接带进来:

  • IsDeleted
  • CreateTime
  • UpdateTime

Request 怎么写

Request 用来承接接口入参。

当前推荐写法:

  • 名字统一是 XxxRequest
  • 优先用 record
  • 属性优先用 init
  • 验证器写在旁边

例如:

public record GetUsersRequest
{
public string Name { get; init; }
public int Age { get; init; }
}

验证器怎么放

验证器一般跟在 Request 后面一起写,命名为 XxxRequestValidator

public class GetUsersRequestValidator : AbstractValidator<GetUsersRequest>
{
public GetUsersRequestValidator()
{
RuleFor(x => x.Name).NotEmpty().WithMessage("姓名不能为空");
}
}

如果你们统一用 FluentValidation,这种写法最省事。

这一层最容易写乱的地方

  • 把数据库实体直接拿来当 DTO
  • Request 里塞数据库字段
  • 在 DTO 里写业务逻辑
  • 一个接口既没有 Request,也没有清晰的入参对象

怎么判断该放 Request 还是 Dto

最简单的分法就是:

  • 发给后端的,放 Request
  • 返回给别人的,放 Dto

如果一个类既想当入参,又想当出参,通常说明边界已经开始混了。

什么时候回来看这页

下面两种情况最适合回来看这页:

  • 你已经开始写 Controller,但还不确定请求对象怎么放
  • 你发现项目里 DTO、Request、Entity 开始混在一起了

如果你只是想先跑通第一版,按 快速开始 里的最小示例先做就够。