本文介绍了.Net核心动态dbContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Startup.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); 

DbContext.cs

 公共类SgAesMasterContext:DbContext{公共DbSet< Company>公司{放;}公共SgAesMasterContext(DbContextOptions< SgAesMasterContext>选项):base(options){}受保护的重写void OnModelCreating(ModelBuilder modelBuilder){}}公共类MyAesMasterContext:DbContext{公共DbSet< Company>公司{放;}公共MyAesMasterContext(DbContextOptions< MyAesMasterContext>选项):base(options){}受保护的重写void OnModelCreating(ModelBuilder modelBuilder){}} 

UnitOfWork.cs

 公共类AesMasterUnitOfWork:IAesMasterUnitOfWork{私有只读SgAesMasterContext sgAesMasterContext;私有只读MyAesMasterContext myAesMasterContext;公共AesMasterUnitOfWork(SgAesMasterContext sgAesMasterContext,MyAesMasterContext myAesMasterContext){this.sgAesMasterContext = sgAesMasterContext;this.myAesMasterContext = myAesMasterContext;}公共SgAesMasterContext SgAesMasterContext {get {return sgAesMasterContext;}}public MyAesMasterContext MyAesMasterContext {get {return myAesMasterContext;}}public CompanyRepository CompanyRepo {get {返回新的CompanyRepository(sgAesMasterContext,myAesMasterContext);}}公共无效Dispose(){sgAesMasterContext.Dispose();myAesMasterContext.Dispose();}} 

CompanyRepository.cs

 公共类CompanyRepository{受保护的只读SgAesMasterContext sgAesMasterContext;受保护的只读MyAesMasterContext myAesMasterContext;公共CompanyRepository(SgAesMasterContext sgAesMasterContext,MyAesMasterContext myAesMasterContext){this.sgAesMasterContext = sgAesMasterContext;this.myAesMasterContext = myAesMasterContext;}公共异步任务<列表<公司>>GetCompanies(字符串国家){列表<公司>公司=新列表< Company>();开关(国家){案例"SG":companies =等待sgAesMasterContext.Companies.Where(x => x.Company_Status =="A"&& x.Status =="0").ToListAsync();休息;案例"MY":companies =等待myAesMasterContext.Companies.Where(x => x.Company_Status =="A"&& x.Status =="0").ToListAsync();休息;}退货公司;}} 

有什么解决方案可以使我的存储库调用动态DbContext而不使用切换用例吗?这是因为,如果我对存储库中的每个功能都使用开关盒,它将变得多余并且难以维护.

解决方案

此解决方案适用于多租户类型的方案,在这些方案中,您具有相同的架构,需要在基于该租户的不同数据库上运行相同的查询./p>

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

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

您可以创建并实现 ITenantDbContextFactory ,它会调查请求以识别要使用的ConnectionString并基于该字符串创建DbContext

剂量注入中的

设置 ITenantDbContextFactory

 公共类TenantDbContextFactory:ITenantDbContextFactory{公共TenantDbContext GetDbContext(){弦国家//阅读请求以识别正确的租户开关(国家){案例"SG":返回新的TenantDbContext("Sg的连接字符串")休息;案例"MY":返回新的TenantDbContext(我的连接字符串")休息;}}} 
 公共类TenantDbContext:DbContext{公共DbSet< Company>公司{放;}公共TenantDbContext(DbContextOptions< TenantDbContext>选项):base(options){}受保护的重写void OnModelCreating(ModelBuilder modelBuilder){}} 
 公共类TenantUnitOfWork:ITenantUnitOfWork{私有只读TenantDbContext tenantDbContext;公共TenantUnitOfWork(ITenantDbContextFactory tenantDbContextFactory){this.tenantDbContext = tenantDbContextFactory.GetDbContext();}公共TenantDbContext TenantDbContext {get {return tenantDbContext;}}public CompanyRepository CompanyRepo {get {返回新的CompanyRepository(tenantDbContext);}}公共无效Dispose(){tenantDbContext.Dispose();}} 
 公共类CompanyRepository{受保护的只读TenantDbContext tenantDbContext;公共CompanyRepository(TenantDbContext tenantDbContext){this.tenantDbContext = tenantDbContext;}公共异步任务<列表<公司>>GetCompanies(){列表<公司>公司=新列表< Company>();companies =等待tenantDbContext.Companies.Where(x => x.Company_Status =="A"&& x.Status =="0").ToListAsync();退货公司;}} 

I has two DbContext sharing the same repository. The following is my existing codes:

Startup.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);

DbContext.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;
    }
}

Is there any solution that I can make my repository to call a dynamic DbContext instead of using switch case? This is because if I using switch case for every function in my repository, it will become redundant and difficult to maintain.

解决方案

This solution is good for multi-tenant types of scenarios, where you have same schema and need to run same query but on different databases based on the tenant.

You can have a single DbContext but pass ConnectionString dynamically to connect to different databases.

Since you have only one DbContext all your repository will depend on that DbContext. Though you need to pass the correct connection string to DbContext based on tenant.

you can create and implement ITenantDbContextFactory which will look into request to identify which ConnectionString to use and create DbContext based on that

setup ITenantDbContextFactory in depedency injection

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;
    }
}

这篇关于.Net核心动态dbContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-27 12:59