Reputation: 1193
I am converting a BDD test project to the use EF core 5.x and SpecFlow 3.x + Specflow.Autofac. When executing the scenario the context is unable to find the connection string from the environmental variables.
Solution setup has the following structure
The scenario dependencies are registered before all scenarios are executed;
public static class DependencyResolver
{
private static IConfiguration config;
[ScenarioDependencies]
public static ContainerBuilder CreateContainerBuilder()
{
var containerBuilder = new ContainerBuilder();
if (config == null)
{
string fullPath = System.Reflection.Assembly.GetAssembly(typeof(DependencyResolver)).Location;
string theDirectory = Path.GetDirectoryName(fullPath);
config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.SetBasePath(theDirectory)
.AddEnvironmentVariables()
.Build();
}
containerBuilder.RegisterInstance(config);
containerBuilder.RegisterTypes(typeof(DependencyResolver).Assembly.GetTypes().Where(t => Attribute.IsDefined(t, typeof(BindingAttribute))).ToArray()).SingleInstance();
containerBuilder.RegisterModule(new DependencyRegister());
containerBuilder.RegisterModule(new BusinessRegister());
containerBuilder.RegisterModule(new DataRegister());
return containerBuilder;
}
}
The DataRegister registers MyContext
;
public class DataRegister : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<MyContext>().AsSelf().InstancePerDependency();
}
}
Inside MyContext
it calls UseSqlServer
to attempt to resolve a environment variable
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.EnableDetailedErrors();
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("Name=ConnectionStrings:MyContext");
}
}
The appsettings.json
located in the BddTest
project
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.EntityFrameworkCore": "Debug",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"MyContext": "--"
}
}
When I attempt to run a scenario the application errors out when attempting to create a database connection inside of MyContext
;
System.InvalidOperationException: 'A named connection string was used, but the name 'ConnectionStrings:MyContext' was not found in the application's configuration. Note that named connection strings are only supported when using 'IConfiguration' and a service provider, such as in a typical ASP.NET Core application.
How do I register my appsettings.json
so that it is available inside the Data
project and can be resolved when using optionsBuilder.UseSqlServer("Name=ConnectionStrings:MyContext");
?
Upvotes: 2
Views: 897
Reputation: 1193
To solve the issue I did something very similar to what @Matheus Dasuke was suggesting. Injected the IConfiguration then read out the values. This means I can get the values of the properties from environmental vars, user secrets, etc.
private static IConfiguration _configuration;
public MyContext(IConfiguration configuration) {
_configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
optionsBuilder.EnableDetailedErrors();
if (!optionsBuilder.IsConfigured) {
var builder = new NpgsqlConnectionStringBuilder("Host=" +
_configuration.GetConnectionString("Host")) {
Password = _configuration["Password"],
Username = _configuration["Username"],
Database = _configuration["Database"],
};
optionsBuilder.UseNpgsql(builder.ConnectionString);
}
}
Upvotes: 1
Reputation: 261
Try this:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.EnableDetailedErrors();
if (!optionsBuilder.IsConfigured)
{
var config = ConfigurationManager.ConnectionStrings["MyContext"];
var conn = new SqlConnection(config.ConnectionString);
options.UseSqlServer(conn);
}
}
Upvotes: 1
Reputation: 1346
Use:
_config.GetValue<string>("ConnectionStrings:MyContext")
Where _config is a DI IConfiguration injected in your constructor where OnConfiguring is.
Upvotes: 0