I am toying with ASP.NET Core 1.1 application and I am trying to read connection string from the configuration file.
My database context class looks like this:
public class ApplicationDbContext : DbContext, IDbContextFactory<ApplicationDbContext>
{
public ApplicationDbContext()
{
}
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
public ApplicationDbContext Create(DbContextFactoryOptions options)
{
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
string connString = "some hardcoded connection string";
builder.UseSqlServer(connString);
return new ApplicationDbContext(builder.Options);
}
}
Running migrations works fine (e.g. dotnet ef database update
).
If I want to remove the hardcoded connection string, I am facing the following problem:
- if I try to inject
IConfiguration
intoApplicationDbContext
, migration will fail withNo parameterless constructor defined for this object.
- without injecting something I cannot find a way to read information from the configuration file
How should I proceed?
Thanks.
[EDIT]
In Startup.cs
I have configured the connection string and it works correctly (runtime):
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
//services.AddApplicationInsightsTelemetry(Configuration);
string connString = ConfigurationExtensions.GetConnectionString(Configuration, "DefaultConnection");
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connString));
services.AddMvc();
}
The problem is that dotnet migrations
seems to require a parameterless constructor in database context and to implement IDbContextFactory<>
and I do not know how to inject the configuration.
Edit after trying IOptions<> with ApplicationDbContext
I have tried suggested solution, but I cannot make it work because dotnet migration
will call the default constructor.
public class ApplicationDbContext : DbContext, IDbContextFactory<ApplicationDbContext>
{
private IOptions<DefaultConnectionValue> ConnOptions;
private string connectionString;
public ApplicationDbContext()
{
Console.WriteLine("Default constructor was called");
}
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IOptions<DefaultConnectionValue> connOptions) : base(options)
{
ConnOptions = connOptions;
connectionString = connOptions.Value.Value;
Console.WriteLine($"Injected connection string = {connectionString}");
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
public ApplicationDbContext Create(DbContextFactoryOptions options)
{
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
//string connString = ConfigurationExtensions.GetConnectionString(null, "DefaultConnection");
builder.UseSqlServer(connectionString);
return new ApplicationDbContext(builder.Options, ConnOptions);
}
I was facing the same problem and I resolved it in the following way:
Thanks to that you will have parameterless constructor required by migrations.
Here is how you can register configuration settings:
And then you can use it as fallow (it's controller example but you can do the same with the DBContext):
For more informations about usage of configuration settings take a look here: Configuration.
UPDATE:
You can also try different approach - read configuration inside of the DBContext constructor: