僅在調用控制器操作時才知道數據庫名稱時注入DbContext

asp.net-core asp.net-web-api c# entity-framework-core

我有一個WebAPI / EF Core後端應用程序,有幾個可能的客戶端數據庫連接到(每個相同的模式,但一次只有一個)。

在訪問WebAPI控制器之前,不知道要連接到哪個數據庫。到那時,使用對starup.cs文件的ConfigureServices()方法中的services.AddDbContext <>()的調用,將DBContext添加為可注入對象為時已晚。

由於每個請求都隔離了DbContext的每個實例,直接從控制器的操作實例化DbContext是否有任何問題,而不是通過使用DI傳遞它?

一般承認的答案

您可以/應該使用抽象工廠來創建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());
    }
}


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow