从 dot net core 中的配置获取多个连接字符串的推荐方法
Recommended way to get multiple connection strings from configuration in dot net core
目前我正在使用 ABP 3.3.0 并且我有 2 个 DbContext。一个是 MSSQL 上下文,另一个是 MySQL。
为了获取连接字符串,我继承了 DefaultConnectionStringResolver
class 并覆盖了 GetNameOrConnectionString
方法。
这在开发中工作正常,但是每当我尝试 运行 单元测试时,我都会得到以下异常
Castle.MicroKernel.Handlers.HandlerException : Can't create component
'Portal.EntityFrameworkCore.CustomerDbConnectionStringResolver' as it
has dependencies to be satisfied.
'Portal.EntityFrameworkCore.CustomerDbConnectionStringResolver' is
waiting for the following dependencies:
- Service 'Microsoft.AspNetCore.Hosting.IHostingEnvironment' which was not registered.
我的理解是因为我正在将 IHostingEnvironment
注入连接字符串解析器。
所以我的问题是,如果我不能将 IHostingEnvironment
注入连接字符串解析器 class,我还能如何访问连接字符串?
为清楚起见,
在开发中,连接字符串存储为用户机密。
在 Staging/Production 中,它们存储在各自的 appSettings.{EnvironmentName}.json 文件中。
这里是连接字符串解析器的实现 class。
public class CustomerDbConnectionStringResolver : DefaultConnectionStringResolver
{
private readonly IHostingEnvironment _env;
public CustomerDbConnectionStringResolver(
IAbpStartupConfiguration configuration,
IHostingEnvironment env)
: base(configuration)
{
_env = env;
}
public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
var configuration = AppConfigurations.Get(_env.ContentRootPath, _env.EnvironmentName,_env.IsDevelopment());
switch (args["DbContextType"].ToString())
{
case "Portal.EntityFrameworkCore.FreeRadiusDbContext":
return configuration.GetConnectionString(PortalConsts.FreeRadiusConnectionStringName);
default:
return configuration.GetConnectionString(PortalConsts.ConnectionStringName);
}
}
}
非常感谢!
编辑
当前 DBContextFactory 的示例。
public class FreeRadiusDbContextFactory : IDesignTimeDbContextFactory<FreeRadiusDbContext>
{
public FreeRadiusDbContext CreateDbContext(string[] args)
{
var builder = new DbContextOptionsBuilder<FreeRadiusDbContext>();
var configuration = AppConfigurations.Get(WebContentDirectoryFinder.CalculateContentRootFolder());
FreeRadiusDbContextConfigurator.Configure(
builder,
configuration.GetConnectionString(PortalConsts.FreeRadiusConnectionStringName)
);
return new FreeRadiusDbContext(builder.Options);
}
}
@aaron 好的所以我想我终于找到了一个适用于所有环境的解决方案。
注意:至于双反斜杠问题,看起来我在环境变量中使用双反斜杠连接字符串,而它本应是单反斜杠。
所以这是最后的 CustomDbConnectionStringResolver
class.
public class CustomDbConnectionStringResolver : DefaultConnectionStringResolver
{
public CustomDbConnectionStringResolver(
IAbpStartupConfiguration configuration
)
: base(configuration)
{
}
public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production";
var configuration = AppConfigurations.Get(Directory.GetCurrentDirectory(), environment, environment == "Development");
switch (args["DbContextType"].ToString())
{
case "Portal.EntityFrameworkCore.FreeRadiusDbContext":
return configuration.GetConnectionString(PortalConsts.FreeRadiusConnectionStringName);
default:
return configuration.GetConnectionString(PortalConsts.ConnectionStringName);
}
}
}
它可以很好地重用模板中已经存在的代码,并且仍然允许为各种环境加载不同的配置。
非常感谢@aaron 的协助!
目前我正在使用 ABP 3.3.0 并且我有 2 个 DbContext。一个是 MSSQL 上下文,另一个是 MySQL。
为了获取连接字符串,我继承了 DefaultConnectionStringResolver
class 并覆盖了 GetNameOrConnectionString
方法。
这在开发中工作正常,但是每当我尝试 运行 单元测试时,我都会得到以下异常
Castle.MicroKernel.Handlers.HandlerException : Can't create component 'Portal.EntityFrameworkCore.CustomerDbConnectionStringResolver' as it has dependencies to be satisfied.
'Portal.EntityFrameworkCore.CustomerDbConnectionStringResolver' is waiting for the following dependencies: - Service 'Microsoft.AspNetCore.Hosting.IHostingEnvironment' which was not registered.
我的理解是因为我正在将 IHostingEnvironment
注入连接字符串解析器。
所以我的问题是,如果我不能将 IHostingEnvironment
注入连接字符串解析器 class,我还能如何访问连接字符串?
为清楚起见, 在开发中,连接字符串存储为用户机密。 在 Staging/Production 中,它们存储在各自的 appSettings.{EnvironmentName}.json 文件中。
这里是连接字符串解析器的实现 class。
public class CustomerDbConnectionStringResolver : DefaultConnectionStringResolver
{
private readonly IHostingEnvironment _env;
public CustomerDbConnectionStringResolver(
IAbpStartupConfiguration configuration,
IHostingEnvironment env)
: base(configuration)
{
_env = env;
}
public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
var configuration = AppConfigurations.Get(_env.ContentRootPath, _env.EnvironmentName,_env.IsDevelopment());
switch (args["DbContextType"].ToString())
{
case "Portal.EntityFrameworkCore.FreeRadiusDbContext":
return configuration.GetConnectionString(PortalConsts.FreeRadiusConnectionStringName);
default:
return configuration.GetConnectionString(PortalConsts.ConnectionStringName);
}
}
}
非常感谢!
编辑
当前 DBContextFactory 的示例。
public class FreeRadiusDbContextFactory : IDesignTimeDbContextFactory<FreeRadiusDbContext>
{
public FreeRadiusDbContext CreateDbContext(string[] args)
{
var builder = new DbContextOptionsBuilder<FreeRadiusDbContext>();
var configuration = AppConfigurations.Get(WebContentDirectoryFinder.CalculateContentRootFolder());
FreeRadiusDbContextConfigurator.Configure(
builder,
configuration.GetConnectionString(PortalConsts.FreeRadiusConnectionStringName)
);
return new FreeRadiusDbContext(builder.Options);
}
}
@aaron 好的所以我想我终于找到了一个适用于所有环境的解决方案。
注意:至于双反斜杠问题,看起来我在环境变量中使用双反斜杠连接字符串,而它本应是单反斜杠。
所以这是最后的 CustomDbConnectionStringResolver
class.
public class CustomDbConnectionStringResolver : DefaultConnectionStringResolver
{
public CustomDbConnectionStringResolver(
IAbpStartupConfiguration configuration
)
: base(configuration)
{
}
public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production";
var configuration = AppConfigurations.Get(Directory.GetCurrentDirectory(), environment, environment == "Development");
switch (args["DbContextType"].ToString())
{
case "Portal.EntityFrameworkCore.FreeRadiusDbContext":
return configuration.GetConnectionString(PortalConsts.FreeRadiusConnectionStringName);
default:
return configuration.GetConnectionString(PortalConsts.ConnectionStringName);
}
}
}
它可以很好地重用模板中已经存在的代码,并且仍然允许为各种环境加载不同的配置。
非常感谢@aaron 的协助!