You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET6中OnModelCreating用HasData报错:无法在模型创建时使用DbContext

问题描述

在.NET6环境下尝试通过EF Core的HasData方法在应用启动前初始化测试数据,重写OnModelCreating方法时出现以下异常:

EntityType '((Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TestApp_40_xUnit_MVC_LibraryApp.Models.Book>)this.Books).EntityType' 引发了System.InvalidOperationException类型的异常,提示“尝试在模型创建过程中使用模型,DbContext实例不能在OnModelCreating中以任何使用正在创建的模型的方式使用”。

应用可正常运行,但测试数据并未插入数据库。相关代码如下:

DbContext代码

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options)
        : base(options)
    {

    }

    public DbSet<Book> Books { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        var _books = new List<Book>()
        {
           new Book()
            {
                Id = Guid.NewGuid(),
                Title="Managing Oneself",
                Description="We live in an age of unprecedented opportunity: with ambition, drive, and talent, you can rise to the top of your chosen profession, regardless of where you started out...",
                Author= "Peter Drucker"
            }
        };

        modelBuilder.Entity<Book>().HasData(_books);
    }
}

Program.cs代码

builder.Services.AddDbContext<AppDbContext>(opt => opt.UseInMemoryDatabase("this-is-just-test"));
builder.Services.AddTransient<IBookService, BookService>();

Book模型类

public class Book
{
    public Guid Id { get; set; }
    [Required]
    public string Author { get; set; }
    [Required]
    public string Title { get; set; }
    public string Description { get; set; }
}
问题原因
  1. 动态Guid触发模型构建冲突:Guid.NewGuid()在OnModelCreating执行时动态生成,而HasData属于模型配置的一部分,EF Core在模型构建阶段会解析种子数据,动态生成的Guid会导致上下文尝试访问未完全构建的模型,进而抛出异常。
  2. 内存数据库未自动执行种子数据:内存数据库不会主动应用HasData中的种子数据,需要显式触发数据库初始化操作才能完成数据插入。
解决方案

1. 替换动态Guid为固定值

HasData要求种子数据的主键是静态确定的值,不能在模型构建阶段动态生成。将Guid.NewGuid()替换为固定的Guid字符串:

修改后的OnModelCreating方法:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    var _books = new List<Book>()
    {
       new Book()
        {
            Id = Guid.Parse("d290f1ee-6c54-4b01-90e6-d701748f0851"), // 固定GUID
            Title="Managing Oneself",
            Description="We live in an age of unprecedented opportunity: with ambition, drive, and talent, you can rise to the top of your chosen profession, regardless of where you started out...",
            Author= "Peter Drucker"
        }
    };

    modelBuilder.Entity<Book>().HasData(_books);
}

2. 显式初始化数据库并应用种子数据

在Program.cs中添加数据库初始化逻辑,通过EnsureCreated()触发内存数据库创建并自动插入种子数据:

修改后的Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<AppDbContext>(opt => opt.UseInMemoryDatabase("this-is-just-test"));
builder.Services.AddTransient<IBookService, BookService>();

var app = builder.Build();

// 初始化数据库并插入种子数据
using (var scope = app.Services.CreateScope())
{
    var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
    dbContext.Database.EnsureCreated(); // 内存数据库会自动执行HasData中的种子数据插入
}

// 其他中间件配置(如路由、授权等)
// app.UseRouting();
// ...

app.Run();
验证效果

启动应用后,内存数据库中会自动插入HasData定义的测试数据,同时模型构建阶段的异常会消失。

内容的提问来源于stack exchange,提问作者Dan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 22:55:18