ASP.Net Core DI 公司上下文提供者? [复制]
Posted
技术标签:
【中文标题】ASP.Net Core DI 公司上下文提供者? [复制]【英文标题】:ASP.Net Core DI company context provider? [duplicate] 【发布时间】:2019-10-04 11:21:06 【问题描述】:我正在使用 ASP.NET Core 3 实现一个 webapi。
在后端,我们有许多具有完全相同架构/表等的公司数据库。
我正在尝试实现一个公司数据库上下文提供程序,它可以让我在运行时解析正确的公司数据库上下文。
在我的 startup.cs 中,我有下面的代码,它应该让你知道我想要做什么:
public void ConfigureServices(IServiceCollection services)
services.AddDbContext<CompanyDbContext>(opt => opt.UseSqlServer(Configuration.GetConnectionString("CompanyDbConnection")));
services.AddScoped<ICompanyRepository, CompanyRepository>();
services.AddDbContext<System.Func<CompanyType, ICompanyDbContext>>(dbContextOptionsBuilder => key =>
switch (key)
case CompanyType.HKG:
return dbContextOptionsBuilder.UseSqlServer(Configuration.GetConnectionString("HkgCompanyDbConnection"));
case CompanyType.SHG:
return dbContextOptionsBuilder.UseSqlServer(Configuration.GetConnectionString("ShgCompanyDbConnection"));
default:
throw new KeyNotFoundException();
);
//...
而不是只有 1 个连接的通用 CompanyContext
,我想将类似服务提供者的东西注入 CompanyRepository
构造函数,然后让我在不同情况下解析不同的公司 dbcontexts存储库函数(通过传递参数)。
这个想法是代码的最后一部分应该根据提供的键返回正确的上下文。但显然最后一部分不起作用。如果不明显,存储库类将保存从数据库返回数据的所有函数。
如何处理这个问题?
【问题讨论】:
您是否有一个上下文指向单个客户数据库或多个上下文指向每个请求的多个客户数据库(范围)? 每个请求我将有多个上下文,它们分别注入,但只有 1 个公司上下文指向 1 个公司数据库,其余的都是独立的。所以我想避免注入所有 20 个左右的“兄弟”上下文。我想为这些注入 1 个通用上下文,这些上下文可以在运行时解析为 20 个左右的公司数据库中的任何一个,具体取决于请求的性质。是的,“Scoped”非常适合这种情况 所以每个请求一个,你不能有两个打开的连接到不同的客户数据库,否则我弄错了 是的,你是对的。每个请求只有 1 个。 【参考方案1】:我最近做了一些非常相似(但不完全)的事情,遇到了this excellent Answer,我认为这正是你所追求的。
基本步骤:
共享委托
public delegate IService ServiceResolver(CompanyType key);
添加要解析的实例
//Note: Default Service Lifetime for AddDbContext is Scoped - perfect!
services.AddDbContext<HkgCompanyContext>(options...);
services.AddDbContext<ShgCompanyContext>(options...);
解析服务
services.AddScoped<ServiceResolver>(serviceProvider => key =>
switch (key)
case CompanyType.HKG:
return serviceProvider.GetService(HkgCompanyContext);
case CompanyType.SHG:
return serviceProvider.GetService(ShgCompanyContext);
default:
throw new KeyNotFoundException();
【讨论】:
这应该对我有用,还没有测试过,但似乎是一个干净的解决方案。唯一需要担心的是,当只有连接字符串不同时,它需要为每个 diff company-context 添加空子类。但这似乎是一个很小的抱怨。【参考方案2】:按照 cmets,您可以这样做,通过检查请求中的公司 ID 或名称是什么,我怀疑这是否是您最终需要的。
哦,是的,我忘记了,这段代码是在 .net core 2.2 上测试过的,但它应该会有所作为。
services.AddScoped<ICompanyType, CompanyType>();
services.AddEntityFrameworkSqlServer();
services.AddDbContext<CompanyDbContext>((serviceProvider, options) =>
var companyCode = serviceProvider.GetRequiredService<ICompanyType>().Get();
string connectionString = string.Empty;
switch (companyCode)
case CompanyType.HKG:
connectionString = Configuration.GetConnectionString("HkgCompanyDbConnection");
break;
case CompanyType.SHG:
connectionString = Configuration.GetConnectionString("ShgCompanyDbConnection");
break;
default:
throw new InvalidOperationException();
options
.UseSqlServer(connectionString)
.UseInternalServiceProvider(serviceProvider);
);
还有一些虚拟公司类型的实现:
public class CompanyType: ICompanyType
public const string HKG = "HKG";
public const string SHG = "SHG";
public string Get()
Random rand = new Random((int) DateTime.UtcNow.Ticks & 0x0000FFFF);
var flipCoin = rand.Next(0, 1);
return flipCoin == 0 ? HKG : SHG;
public interface ICompanyType
// dummy code, to be replaced with what is needed
string Get();
【讨论】:
谢谢,我还没有对此进行测试,因为其他解决方案更接近我已经拥有的解决方案,并且不需要我为 CompanyType 创建自定义类(它只是一个枚举)。如果您对切换键类有更复杂的需求,也许对其他人来说这会更好。以上是关于ASP.Net Core DI 公司上下文提供者? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)