ASP.Net 核心 DI 公司上下文提供者?
ASP.Net Core DI company context provider?
我正在使用 ASP.NET Core 3 实现一个 webapi。
在后端,我们有许多完全相同的公司数据库schema/tables等等
我正在尝试实现一个公司数据库上下文提供程序,它可以让我在运行时解析正确的公司数据库上下文。
在我的 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
我想注入服务提供者之类的东西,但是对于 dbcontexts 到 CompanyRepository
构造函数中,然后让我解析不同的公司存储库函数中不同情况下的 dbcontexts(通过传递参数)。
想法是代码的最后一部分应该 return 基于提供的密钥的正确上下文。但显然最后一部分不起作用。如果不是很明显,存储库 class 将保存所有函数 return 从数据库中获取数据。
如何解决这个问题?
根据评论,这是你可以做的,通过检查请求中的公司 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();
}
我最近做了一些非常相似(但不完全)的事情并遇到了 我认为这正是您所追求的。
基本步骤:
共享代表
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();
}
}
我正在使用 ASP.NET Core 3 实现一个 webapi。
在后端,我们有许多完全相同的公司数据库schema/tables等等
我正在尝试实现一个公司数据库上下文提供程序,它可以让我在运行时解析正确的公司数据库上下文。
在我的 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
我想注入服务提供者之类的东西,但是对于 dbcontexts 到 CompanyRepository
构造函数中,然后让我解析不同的公司存储库函数中不同情况下的 dbcontexts(通过传递参数)。
想法是代码的最后一部分应该 return 基于提供的密钥的正确上下文。但显然最后一部分不起作用。如果不是很明显,存储库 class 将保存所有函数 return 从数据库中获取数据。
如何解决这个问题?
根据评论,这是你可以做的,通过检查请求中的公司 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();
}
我最近做了一些非常相似(但不完全)的事情并遇到了
基本步骤:
共享代表
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();
}
}