根据微软官方文档的说法,有两种方法可以实现在一个app中同时适应多种不同类型的数据库,并且全部支持migrations操作。其一,使用两个dbcontext;其二,修改migration文件,添加特定数据库类型的Annotation。
本人在实际使用过程中发现,第二种情况几乎很难调通,总是在migration操作时遭遇各种奇怪问题,而且这种操作似乎也不太”干净“;第一种操作,一开始无论如何也调不通,后来发现是dbcontext的注入方式有问题,不能像默认模板生成的那样使用options参数,而是应该使用空白的构造方法,具体代码如下:
DbContext:
public class ApplicationDbContext : IdentityDbContext { public DbSet<Location> Locations { get; set; } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); } } public class PgDbContext : ApplicationDbContext { protected override void OnConfiguring(DbContextOptionsBuilder options) { options.UseNpgsql(Startup.Configuration.GetConnectionString("DefaultConnection")); } } public class MsDbContext : ApplicationDbContext { protected override void OnConfiguring(DbContextOptionsBuilder options) { options.UseSqlServer(Startup.Configuration.GetConnectionString("DefaultConnection")); } }
注意覆盖的方法是OnConfiguring。
然后就是Startup中根据配置的数据库类型注入不同的dbcontext:
public void ConfigureServices(IServiceCollection services) { var dbType = Configuration.GetValue<string>("DbType"); //多种数据库支持 if (dbType == "PGSQL") services.AddDbContext<ApplicationDbContext, PgDbContext>(); else services.AddDbContext<ApplicationDbContext, MsDbContext>(); services.AddDefaultIdentity<IdentityUser>(options => { options.SignIn.RequireConfirmedAccount = false; }).AddEntityFrameworkStores<ApplicationDbContext>(); services.AddControllersWithViews(); services.AddRazorPages(); }
然后,别忘了,给不同的数据库类型(dbcontext)建立不同的migration:
Add-Migration Initial -Context MsDbContext -OutputDir Migrations/Mssql
Add-Migration Initial -Context PgDbContext -OutputDir Migrations/Pssql
以上命令分别建立不同的migrations。
最后,在执行context.Database.Migrate()时,context就会根据数据库类型自动寻找正确的migrations了。
关键:不再通过options参数构造dbcontext。