如何在运行时修改IDesignTimeDbContextFactory的连接字符串
解决方案:动态配置连接字符串与分库存储实体
一、运行时动态修改IDesignTimeDbContextFactory的连接字符串
IDesignTimeDbContextFactory主要用于EF Core设计时操作(比如迁移),要实现动态传入连接字符串,有两种实用方式:
1. 命令行参数传递
修改工厂类,直接读取命令行传入的参数作为连接字符串,执行迁移时手动指定即可:
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<erp_colombiaDbContext> { public erp_colombiaDbContext CreateDbContext(string[] args) { // 执行迁移时用:dotnet ef migrations add InitialCreate -- "你的连接字符串" string connectionString = args.Length > 0 ? args[0] : throw new ArgumentException("必须传入连接字符串参数"); var options = new DbContextOptionsBuilder<erp_colombiaDbContext>() .UseMySql( connectionString, optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(DesignTimeDbContextFactory).Assembly.FullName)) .Options; return new erp_colombiaDbContext(options); } }
2. 环境变量读取
如果不想每次手动传参,可从环境变量读取,适合自动化部署场景:
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<erp_colombiaDbContext> { public erp_colombiaDbContext CreateDbContext(string[] args) { string connectionString = Environment.GetEnvironmentVariable("ERP_CONNECTION_STRING") ?? throw new InvalidOperationException("请先设置ERP_CONNECTION_STRING环境变量"); var options = new DbContextOptionsBuilder<erp_colombiaDbContext>() .UseMySql( connectionString, optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(DesignTimeDbContextFactory).Assembly.FullName)) .Options; return new erp_colombiaDbContext(options); } }
二、将不同实体映射到不同数据库
在MySQL中实现分库存储,推荐两种方案:
方案1:单个DbContext指定实体的目标数据库
在OnModelCreating中,通过ToTable方法为实体指定对应的数据库(第二个参数为数据库名):
public class erp_colombiaDbContext : IdentityDbContext<Employee, Entities.Type, ulong> { public erp_colombiaDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // Family表存储到database2 builder.Entity<Family>() .ToTable("Family", "database2") .HasIndex(t => t.FamilyName).IsUnique(); // NewsAuthor表存储到database1 builder.Entity<NewsAuthor>() .ToTable("NewsAuthor", "database1") .HasKey(t => new { t.NewsId, t.EmployeeId }); } }
注意:这种方式需要确保当前数据库用户有权限访问两个数据库,操作不同实体时EF Core会自动切换数据库。
方案2:拆分多个DbContext(更推荐)
把不同数据库的实体拆分到独立的DbContext中,逻辑更清晰,迁移也能分别执行:
// 管理database1的DbContext public class Db1Context : IdentityDbContext<Employee, Entities.Type, ulong> { public Db1Context(DbContextOptions<Db1Context> options) : base(options) { } public DbSet<NewsAuthor> NewsAuthors { get; set; } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); builder.Entity<NewsAuthor>().HasKey(t => new { t.NewsId, t.EmployeeId }); } } // 管理database2的DbContext public class Db2Context : DbContext { public Db2Context(DbContextOptions<Db2Context> options) : base(options) { } public DbSet<Family> Families { get; set; } protected override void OnModelCreating(ModelBuilder builder) { builder.Entity<Family>().HasIndex(t => t.FamilyName).IsUnique(); } }
使用时分别注入两个DbContext的实例,各自对应不同的连接字符串,迁移时指定DbContext:
dotnet ef migrations add InitialDb1 --context Db1Context dotnet ef migrations add InitialDb2 --context Db2Context
内容的提问来源于stack exchange,提问作者J.C
相关产品推荐
相关产品推荐

