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

WPF(.NET6)中EF Core给Sqlite关联模型Seed数据遇DbContext创建失败

问题原因及解决方案

错误原因

  1. 上下文构造函数的干扰操作:ContactsContext的无参构造函数中调用了Database.EnsureDeleted()和Database.EnsureCreated(),这两个方法会直接创建/删除数据库。EF Core迁移工具在实例化上下文以生成迁移时,会执行这些操作,导致工具无法正常获取模型元数据,最终引发实例创建失败。
  2. 缺少设计时构造函数:EF Core迁移工具默认需要一个接收DbContextOptions<ContactsContext>参数的构造函数来正确配置上下文,你的上下文未提供该构造函数,导致工具无法初始化上下文。

解决步骤

1. 修改上下文构造函数

移除构造函数中的数据库创建逻辑,添加供迁移工具使用的带参数构造函数:

public class ContactsContext : DbContext
{
    public DbSet<Contact> Contacts => Set<Contact>();
    public DbSet<ContactGroup> ContactGroups => Set<ContactGroup>();

    // 供迁移工具使用的构造函数
    public ContactsContext(DbContextOptions<ContactsContext> options) : base(options)
    {
    }

    // 无参构造函数(供应用内使用)
    public ContactsContext()
    {
        // 移除 EnsureDeleted 和 EnsureCreated,移到应用启动逻辑中
    }
        
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // 仅当未配置选项时才设置默认连接字符串
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlite("Data Source=contacts.db");
        }
    }
        
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    { 
        modelBuilder.Entity<ContactGroup>(entity =>
        {
            entity.HasKey(x => x.Id);
            entity.Property(x => x.Name).IsRequired(); // 补充对应模型的[Required]特性配置
            entity.HasOne(x => x.Parent)
                .WithMany(x => x.SubGroups)
                .HasForeignKey(x => x.ParentId)
                .IsRequired(false)
                .OnDelete(DeleteBehavior.Cascade);
            // 显式配置Contact与ContactGroup的关联
            entity.HasMany(x => x.Contacts)
                .WithOne(x => x.Parent)
                .HasForeignKey(x => x.ParentId)
                .IsRequired(false);
        });

        // 使用固定Guid作为种子数据的Id,确保迁移一致性
        var groupId = Guid.Parse("d290f1ee-6c54-4b01-90e6-d701748f0851");
        var contact1Id = Guid.Parse("7a7e0a4a-3b4b-4c4c-8d8d-1234567890ab");
        var contact2Id = Guid.Parse("f47ac10b-58cc-4372-a567-0e02b2c3d479");

        Contact c1 = new Contact { Id = contact1Id, Title = "Mr", FirstName = "John", LastName = "Smith", ParentId = groupId };
        Contact c2 = new Contact { Id = contact2Id, Title = "Mrs", FirstName = "Jane", LastName = "Doe" };
        ContactGroup g1 = new ContactGroup { Id = groupId, Name = "Social" };

        modelBuilder.Entity<ContactGroup>().HasData(g1);
        modelBuilder.Entity<Contact>().HasData(c1, c2);
    }
}

2. 调整应用启动逻辑

将原来构造函数中的数据库初始化逻辑移到WPF应用的启动代码中(例如App.xaml.cs的OnStartup方法):

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    using var context = new ContactsContext();
    context.Database.EnsureDeleted();
    context.Database.EnsureCreated();
    // 若使用迁移管理数据库,可替换为:context.Database.Migrate();
}

3. 重新生成迁移

打开命令行进入项目目录,执行以下命令:

dotnet ef migrations add InitialCreate
dotnet ef database update

额外说明

  • 种子数据建议使用固定Guid,避免每次运行生成新Id导致迁移文件重复或数据不一致。
  • 显式配置实体间的关联关系,能让EF Core更清晰地识别模型结构,减少潜在的映射错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 20:20:26