我有一个WebAPI / EF Core后端应用程序,它有几个可能的客户端数据库连接到(每个相同的模式,但一次只有一个)。
在访问WebAPI控制器之前,不知道要连接到哪个数据库。到那时,使用对starup.cs文件的ConfigureServices()方法中的services.AddDbContext<>()的调用将DBContext添加为可注入对象为时已晚。
由于每个请求都隔离了DbContext的每个实例,直接从控制器的动作实例化DbContext是否有任何问题,而不是通过使用DI传递它?
答案 0 :(得分:2)
您可以/应该使用抽象工厂来创建DbContext
public interface IDbContextFactory
{
ApplicationContext Create();
}
public class DbContextFactory() : IDbContextFactory, IDisposable
{
private ApplicationContext context;
private bool disposing;
public DbContextFactory(/* other dependencies here */)
{
}
public ApplicationContext Create(string tenantId)
{
if(this.context==null)
{
// and the connection string and replace the database name in it
// with the tenantId or whatever means you have to determine
// which database to access
string connectionString = ...;
var dbContextBuilder = new DbContextOptionsBuilder();
dbContextBuilder.UseSqlServer(connectionString);
this.context = new ApplicationContext(dbContextBuilder);
}
return this.context;
}
public void Dispose(){
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing){
if (disposing){
disposing?.Dispose();
}
}
}
注册
services.AddScoped<IDbContextFactory, DbContextFactory>();
并在控制器中使用它,如下所示
public class MyController : Controller
{
private readonly IDbContextFactory contextFactory;
public MyController(IMyContextFactory contextFactory)
{
this.contextFactory = contextFactory;
}
public Task<IActionResult> GetSomeData(string tenantId)
{
var context = contextFactory.Create(tenantId);
return Ok(await context.Data.Where(...).ToListAsync());
}
}