EF Core如何避免OnModelCreating中数据种子被重复执行?
问题背景
根据文档说明:
通常,
OnModelCreating()仅在派生上下文的第一个实例创建时调用一次,该上下文的模型会被缓存,供应用域内所有后续上下文实例使用。
以下是我的代码:
protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); builder.ApplyConfiguration(new StudentConfiguration()); }
internal class StudentConfiguration : IEntityTypeConfiguration<Student> { public void Configure(EntityTypeBuilder<Student> builder) { Console.WriteLine($">>>>>>>>>>>>>>>>>>>>> {nameof(StudentConfiguration)}"); builder.HasData( new Student { Name = "Albert Einstein", Age = 100 }, new Student { Name = "Isaac Newton", Age = 400 } ); } }
执行dotnet ef database update时会触发数据种子插入,这符合预期。但启动应用后,首次数据库访问会触发一次OnModelCreating()(控制台输出对应的日志),且每次重启应用都会触发一次Configure()方法,然而数据库中并未出现重复的种子数据。我想了解EF Core是如何确保数据种子仅执行一次的,尽管Configure()会在每个应用域启动时被调用一次?
解答
核心原因在于:你用HasData定义的是迁移式种子数据,它的插入逻辑和应用运行时的模型构建完全无关。
- 当你执行
dotnet ef migrations add和dotnet ef database update时,EF Core会分析HasData里的内容,把这些种子数据转换成对应的SQL插入语句,写入到迁移脚本中。只有在执行迁移脚本的时候,这些数据才会被插入到数据库里。 - 应用启动时调用
OnModelCreating和Configure,只是在构建EF Core的实体模型(用来映射数据库结构、生成查询等),这个过程并不会执行任何数据插入操作。你看到的控制台日志只是模型构建时执行了Configure方法里的代码,但builder.HasData在这里的作用仅仅是向模型元数据中添加种子数据的描述,不是直接操作数据库。
简单说,HasData的种子数据是通过迁移脚本一次性写入数据库的,后续应用重启时,哪怕模型构建过程反复调用Configure,也不会再触发数据插入——因为插入动作已经在迁移执行时完成了,模型构建阶段不负责执行数据写入。
另外补充:如果用的是EF Core 3.0+的EnsureCreated方法,它会在数据库不存在时自动创建库并插入HasData的种子数据,但这也只会执行一次(数据库创建完成后就不会再跑了),和迁移的逻辑类似,都是基于数据库是否已存在对应的结构/数据来判断的。
内容的提问来源于stack exchange,提问作者D G
相关产品推荐
相关产品推荐

