我有一个带有Entity Framework Core的Asp.Net Core应用程序,我初始化如下:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(sqlConnectionString));
这很好用,但我有一个场景,我需要从主数据库读取/写入正常操作但是对于某些操作我需要从备用服务器读取(复制目标只读我们用于报告)。
通过新的Core API通过依赖注入和StartUp.cs中的配置完成所有工作,我如何切换连接字符串,但使用相同的ApplicationDbContext类?
我知道有一个选项可能是我使用不同的连接字符串向DI系统注册的ApplicationDbContext类的副本,但是我想避免维护两个相同的DBContext对象,因为有时我需要从不同的数据库服务器读取(但具有完全相同的模式)。
提前感谢任何指针!
答案 0 :(得分:11)
您需要两个DbContexts。
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
public class MyBloggingContext : BloggingContext
{
}
public class MyBackupBloggingContext : BloggingContext
{
}
你可以这样注册:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyBloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContext<MyBackupBloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("BackupConnection")));
}
答案 1 :(得分:4)
可以这样做(通过.net core 3.1测试):
public abstract partial class BloggingContext<T> : DbContext where T : DbContext
{
private readonly string _connectionString;
protected BloggingContext(string connectionString) { _connectionString = connectionString; }
protected BloggingContext(DbContextOptions<T> options) : base(options) { }
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(_connectionString);
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
...
}
}
public class MyBloggingContext : BloggingContext<MyBloggingContext>
{
protected BloggingContext(string connectionString) { _connectionString = connectionString; }
protected BloggingContext(DbContextOptions<T> options) : base(options) { }
}
public class MyBackupBloggingContext : BloggingContext<MyBackupBloggingContext>
{
protected MyBackupBloggingContext(string connectionString) { _connectionString = connectionString; }
protected MyBackupBloggingContext(DbContextOptions<T> options) : base(options) { }
}
在Startup.cs中
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyBloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContext<MyBackupBloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("BackupConnection")));
}
答案 2 :(得分:0)
可以使用IServiceProvider
解析连接字符串。在下面的示例中,我将查询参数映射到appsettings.json
的配置中,但是您可以注入所需的任何其他逻辑。
services.AddDbContext<ApplicationDbContext>((services, optionsBuilder) =>
{
var httpContextAccessor = services.GetService<IHttpContextAccessor>();
var requestParam = httpContextAccessor.HttpContext.Request.Query["database"];
var connStr = Configuration.GetConnectionString(requestParam);
optionsBuilder.UseSqlServer(connStr);
});
查询中的 ?database=Connection1
和?database=Connection2
将导致使用不同的连接字符串。缺少参数时,值得提供默认值。