站点图标 神之眼的博客

关于EF Core 生成数据库表的实体模型(Entity)和前端提交数据的校验模型(DTO/Input Model)

當前文章的短網址連結為: https://unos.top/aprp

最佳实践:

强烈推荐将 EF Core 生成数据库表的实体模型(Entity)和前端提交数据的校验模型(DTO/Input Model)完全分开,而不是直接在 EF Core Entity 上添加 [Required]、[EmailAddress] 等 DataAnnotations 用于前端校验。

为什么不能直接在 EF Core Entity 上加校验 Annotations?

微软官方和社区主流推荐(Web API + EF Core 项目):使用 DTO 专门负责输入/输出和校验,Entity 只负责数据层。

推荐架构分层(最佳实践)

  1. Data Layer:EF Core Entity(可少量加 DB 约束注解)。
  2. Application/API Layer:DTO(带完整 DataAnnotations 校验)。
  3. Mapping:用 AutoMapper(推荐)或手动 new User { … } 把 DTO 转成 Entity。

完整案例(.NET 10 LTS + EF Core + Web API / Minimal API)

假设我们有一个 User 实体,需要前端提交创建用户。

1. EF Core Entity(Data/Models/User.cs)

using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;  // 这里只用于 DB 约束

public class User
{
    [Key]
    public int Id { get; set; }

    [Required]                    // 只影响 DB 列 NOT NULL
    [MaxLength(100)]              // 只影响 DB 列长度
    public string Name { get; set; } = string.Empty;

    [Required]
    [MaxLength(200)]
    public string Email { get; set; } = string.Empty;

    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}
C#

2. 前端提交用的 DTO(Application/Dtos/CreateUserDto.cs)

using System.ComponentModel.DataAnnotations;

public class CreateUserDto
{
    [Required(ErrorMessage = "姓名不能为空")]
    [StringLength(100, MinimumLength = 2, ErrorMessage = "姓名长度必须在2-100字符之间")]
    public string Name { get; set; } = string.Empty;

    [Required(ErrorMessage = "邮箱不能为空")]
    [EmailAddress(ErrorMessage = "邮箱格式不正确")]
    public string Email { get; set; } = string.Empty;

    // 可以加更多自定义校验,如密码确认、手机号正则等
}
C#

3. Controller 写法(传统 Web API)

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly AppDbContext _context;

    public UsersController(AppDbContext context) => _context = context;

    [HttpPost]
    public async Task<IActionResult> Create([FromBody] CreateUserDto dto)
    {
        if (!ModelState.IsValid)   // ASP.NET Core 自动根据 DataAnnotations 校验
        {
            return BadRequest(ModelState);  // 返回 400 + 详细错误
        }

        var user = new User
        {
            Name = dto.Name,
            Email = dto.Email
        };

        _context.Users.Add(user);
        await _context.SaveChangesAsync();

        return CreatedAtAction(nameof(GetById), new { id = user.Id }, user);
    }
}
C#

4. .NET 10 Minimal API 写法(更简洁,内置校验支持)

在 Program.cs 里先注册:

builder.Services.AddValidation();   // .NET 10 新特性
C#

然后直接用:

app.MapPost("/api/users", async (CreateUserDto dto, AppDbContext db) =>
{
    // .NET 10 会自动校验 DataAnnotations,无需手动 ModelState
    var user = new User { Name = dto.Name, Email = dto.Email };
    db.Users.Add(user);
    await db.SaveChangesAsync();
    return Results.Created($"/api/users/{user.Id}", user);
});
C#

额外提示(进阶最佳实践)

退出移动版