WPF(.NET6)中EF Core给Sqlite关联模型Seed数据遇DbContext创建失败
问题原因及解决方案
错误原因
- 上下文构造函数的干扰操作:
ContactsContext的无参构造函数中调用了Database.EnsureDeleted()和Database.EnsureCreated(),这两个方法会直接创建/删除数据库。EF Core迁移工具在实例化上下文以生成迁移时,会执行这些操作,导致工具无法正常获取模型元数据,最终引发实例创建失败。 - 缺少设计时构造函数: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
相关产品推荐
相关产品推荐

