在WPF(.NET5)中使用EFCore进行数据迁移的障碍主要是EFCore无法创建DbContext,通过实现IDesignTimeDbContextFactory接口可以通过自主创建DbContext,解决EFCore找不到数据库上下文的问题。
参考资料:WPF with entity framework on net core - unable to create and object of type AppDbContext
本文的环境为:WPF + .NET5 + EF Core + SQLite。
1、DesignTimeDbContextFactory
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<SqliteDbContext> { public SqliteDbContext CreateDbContext(string[] args) { var optionsBuilder = new DbContextOptionsBuilder<SqliteDbContext>(); optionsBuilder.UseSqlite("Data Source=Data.db"); return new SqliteDbContext(optionsBuilder.Options, null); } }
2、SqliteDbContext
public class SqliteDbContext : DbContext { public DbSet<User> Users { get; set; } public DbSet<UserRole> UserRoles { get; set; } private readonly string _connectionString; // ReSharper disable once IdentifierTypo public SqliteDbContext(DbContextOptions<SqliteDbContext> options, IConfigService configService) : base(options) { _connectionString = configService?.SqliteConnectionString; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!string.IsNullOrWhiteSpace(_connectionString)) { optionsBuilder.UseSqlite(_connectionString); } optionsBuilder.UseLazyLoadingProxies(); base.OnConfiguring(optionsBuilder); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //添加角色 modelBuilder.Entity<UserRole>().HasData( new UserRole() {Id = 1, Name = @"user", Remark = @"普通用户"}, new UserRole() {Id = 2, Name = @"admin", Remark = @"管理员"} ); //添加用户 modelBuilder.Entity<User>().HasData( new User() { Id = 1, UserName = @"test", Password = @"123456", CreateTime = DateTime.Now, UserRoleId = 1 }, new User() { Id = 2, UserName = @"admin", Password = @"123456", CreateTime = DateTime.Now, UserRoleId = 2 } ); } }
3、注意事项
(1)IDesignTimeDbContextFactory接口的泛型必须是已定义的DbContext(比如文中的SqliteDbContext)。
(2)optionsBuilder.UseSqlite中的连接字符串必须明确定义,这里定义为常量,也可以是从配置中加载的字符串。使用其他数据库,例如MySQL,也是一样的。
(3)进行数据迁移的时候要确保安装这些包:Microsoft.EntityFrameworkCore、Microsoft.EntityFrameworkCore.Sqlite、Microsoft.EntityFrameworkCore.Tools。
4、常用数据迁移命令
可以在程序包管理器控制台上执行数据迁移命令,当然也可以直接在命令行中执行。
(1)配置Migration
Enable-Migrations -ContextTypeName "TestWpf.SqliteDbContext" -ProjectName " TestWpf" -StartUpProjectName " TestWpf" -ConnectionStringName "Data Source=Data.db" -Verbose
(2)添加数据迁移
add-migration InitialMigration -Context LabelPrintingSystem.Database.SqliteDbContext
(3)更新数据库
update-database