避免ASP.NET Core 2.0 EF模型更新丢失DataAnnotations的问题
你遇到的这个问题是Entity Framework Core Scaffold工具的典型局限——它会完全覆盖自动生成的实体类文件,所以手动添加的DataAnnotations自然会被清除。下面是几种实用的解决办法,按推荐程度排序:
1. 使用分部类+元数据类(最推荐)
核心思路是把自定义的DataAnnotations和自动生成的实体类分离开:自动生成的实体类本身是partial类型,我们可以新建一个同名的分部类,通过[MetadataType]特性关联一个专门存放注解的元数据类。这样每次Scaffold更新时,只会覆盖自动生成的那个分部类文件,我们自己写的元数据类和分部类不会被改动。
示例代码:
自动生成的Models/Company.cs(会被Scaffold覆盖)
namespace YourProject.Models { public partial class Company { public Guid CompanyId { get; set; } public string Name { get; set; } // 其他自动生成的属性 } }
手动创建的Models/Company.Metadata.cs(不会被覆盖)
using System.ComponentModel.DataAnnotations; namespace YourProject.Models { // 元数据类,存放所有自定义注解 public class CompanyMetadata { [Required(ErrorMessage = "公司ID不能为空")] public Guid CompanyId { get; set; } [StringLength(100, ErrorMessage = "公司名称不能超过100个字符")] [Display(Name = "公司名称")] public string Name { get; set; } } // 关联元数据的分部类 [MetadataType(typeof(CompanyMetadata))] public partial class Company { } }
2. 用Fluent API替代DataAnnotations
如果你愿意放弃DataAnnotations,改用EF Core的Fluent API来配置实体验证和映射规则,也是一个不错的选择。因为Fluent API的配置代码写在DbContext的OnModelCreating方法里(或者单独的配置类中),Scaffold工具默认不会覆盖DbContext(除非你特意指定了覆盖它的参数)。
示例:
单独的实体配置类(推荐,避免DbContext过于臃肿)
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace YourProject.Models.Configurations { public class CompanyConfiguration : IEntityTypeConfiguration<Company> { public void Configure(EntityTypeBuilder<Company> builder) { builder.Property(c => c.Name) .IsRequired() .HasMaxLength(100); // 其他配置规则 } } }
在DbContext中加载配置
using Microsoft.EntityFrameworkCore; namespace YourProject.Models { public partial class MyDbContext : DbContext { protected override void OnModelCreating(ModelBuilder modelBuilder) { // 加载所有实体配置类 modelBuilder.ApplyConfigurationsFromAssembly(typeof(MyDbContext).Assembly); // 保留Scaffold自动生成的其他配置(如果有的话) base.OnModelCreating(modelBuilder); } } }
这样每次Scaffold更新模型时,只要OnModelCreating里的ApplyConfigurationsFromAssembly代码不被删除,你的配置就会一直生效。
3. 自定义Scaffold模板(适合频繁更新模型的场景)
如果你的项目需要频繁从数据库更新模型,且希望自动生成的实体类直接包含特定的DataAnnotations,可以自定义EF Core的Scaffold模板。ASP.NET Core 2.0中,你可以通过修改Razor模板文件(.cshtml)来控制生成的实体类内容,比如自动添加[Required]、[StringLength]等注解。
步骤大概是:
- 导出默认的Scaffold模板到项目中:使用命令
dotnet ef dbcontext scaffold --help查看模板导出选项,或者在Package Manager Console中使用对应的命令。 - 修改模板文件,添加你需要的DataAnnotations逻辑(比如根据数据库字段的是否为空、长度等自动生成注解)。
- 之后每次执行Scaffold命令时,指定使用自定义模板。
不过这个方法有一定学习成本,适合对EF Scaffold工具比较熟悉的开发者。
关于你当前的ViewModel方案
你用ViewModel来存放验证规则的方式也是可行的,尤其是在实体类和展示层需要不同规则的场景下。但如果希望实体类本身就携带数据验证规则,上面的分部类方案会更直接。
内容的提问来源于stack exchange,提问作者Eyal

