首页 > 解决方案 > .Net Core 动态 dbContext

问题描述

我有两个 DbContext 共享同一个存储库。以下是我现有的代码:

启动.cs

        services.AddDbContext<SgAesMasterContext>(options =>  options.UseSqlServer(Configuration.GetConnectionString("SgAesMasterContext"),
            b => b.UseRowNumberForPaging()), ServiceLifetime.Scoped);

        services.AddDbContext<MyAesMasterContext>(options => options.UseSqlServer(Configuration.GetConnectionString("MyAesMasterContext"),
            b => b.UseRowNumberForPaging()), ServiceLifetime.Scoped);

数据库上下文.cs

public class SgAesMasterContext : DbContext
{
    public DbSet<Company> Companies { get; set; }

    public SgAesMasterContext(DbContextOptions<SgAesMasterContext> options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    }
}

public class MyAesMasterContext : DbContext
{
    public DbSet<Company> Companies { get; set; }

    public MyAesMasterContext(DbContextOptions<MyAesMasterContext> options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    }
}

UnitOfWork.cs

public class AesMasterUnitOfWork: IAesMasterUnitOfWork
{
    private readonly SgAesMasterContext sgAesMasterContext;
    private readonly MyAesMasterContext myAesMasterContext;

    public AesMasterUnitOfWork(SgAesMasterContext sgAesMasterContext, MyAesMasterContext myAesMasterContext)
    {
        this.sgAesMasterContext = sgAesMasterContext;
        this.myAesMasterContext = myAesMasterContext;
    }

    public SgAesMasterContext SgAesMasterContext { get { return sgAesMasterContext; } }
    public MyAesMasterContext MyAesMasterContext { get { return myAesMasterContext; } }
    public CompanyRepository CompanyRepo { get { return new CompanyRepository(sgAesMasterContext, myAesMasterContext); } }

    public void Dispose()
    {
        sgAesMasterContext.Dispose();
        myAesMasterContext.Dispose();
    }
}

CompanyRepository.cs

public class CompanyRepository
{
    protected readonly SgAesMasterContext sgAesMasterContext;
    protected readonly MyAesMasterContext myAesMasterContext;

    public CompanyRepository(SgAesMasterContext sgAesMasterContext, MyAesMasterContext myAesMasterContext)
    {
        this.sgAesMasterContext = sgAesMasterContext;
        this.myAesMasterContext = myAesMasterContext;
    }

    public async Task<List<Company>> GetCompanies(string country)
    {
        List<Company> companies = new List<Company>();

        switch (country)
        {
            case "SG":
                companies = await sgAesMasterContext.Companies.Where(x => x.Company_Status == "A" && x.Status == "0").ToListAsync();
                break;
            case "MY":
                companies = await myAesMasterContext.Companies.Where(x => x.Company_Status == "A" && x.Status == "0").ToListAsync();
                break;
        }

        return companies;
    }
}

有什么解决方案可以让我的存储库调用动态 DbContext 而不是使用 switch case?这是因为如果我对存储库中的每个函数都使用 switch case,它将变得多余且难以维护。

标签: c#asp.net-core

解决方案


此解决方案适用于多租户类型的场景,在这些场景中,您具有相同的架构并且需要在基于租户的不同数据库上运行相同的查询。

您可以拥有一个 DbContext,但动态传递 ConnectionString 以连接到不同的数据库。

由于您只有一个 DbContext,因此您的所有存储库都将依赖于该 DbContext。尽管您需要根据租户将正确的连接字符串传递给 DbContext。

您可以创建并实现ITenantDbContextFactorywhich 将查看请求以确定要使用的 ConnectionString 并基于该请求创建 DbContext

ITenantDbContextFactory在依赖注入中设置

public class TenantDbContextFactory : ITenantDbContextFactory 
{
       public TenantDbContext GetDbContext()
       {
             string country;
               // Read Request to identify correct tenant
             switch (country)
             {
                 case "SG":
                      return new TenantDbContext("connectionstring for Sg")
                break;
                 case "MY":
                      return new TenantDbContext("connectionstring for my")
                break;
             }
       }
}
public class TenantDbContext: DbContext
{
    public DbSet<Company> Companies { get; set; }

    public TenantDbContext(DbContextOptions<TenantDbContext> options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    }
}
public class TenantUnitOfWork: ITenantUnitOfWork
{
    private readonly TenantDbContext tenantDbContext;

    public TenantUnitOfWork(ITenantDbContextFactory tenantDbContextFactory)
    {
        this.tenantDbContext= tenantDbContextFactory.GetDbContext();
    }

    public TenantDbContext  TenantDbContext  { get { return tenantDbContext; } }
    public CompanyRepository CompanyRepo { get { return new CompanyRepository(tenantDbContext); } }

    public void Dispose()
    {
        tenantDbContext.Dispose();
    }
}
public class CompanyRepository
{
    protected readonly TenantDbContext tenantDbContext ;

    public CompanyRepository(TenantDbContext tenantDbContext)
    {
        this.tenantDbContext = tenantDbContext ;
    }

    public async Task<List<Company>> GetCompanies()
    {
        List<Company> companies = new List<Company>();

        companies = await tenantDbContext.Companies.Where(x => x.Company_Status == "A" && x.Status == "0").ToListAsync();

        return companies;
    }
}

推荐阅读