1

I have ASP.Net Core 3 application with Entity Framework. Database credentials are in AWS Systems Manager. AWS is not important; what is important that credentials are retrieved at runtime). In Core 2 I was injecting AWS service in Program.cs, but in Core 3 it is no longer possible.

This is relevant part of what I have (for clarification, IAmazonSimpleSystemsManagement is AWS service, and SSMService is my service that retrieves the credentials:

public void ConfigureServices(IServiceCollection services) {
    services.AddAWSService<IAmazonSimpleSystemsManagement>();
    services.AddSingleton<ISSMService, SSMService>();

    services.AddDbContext<MyContext>();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
    IOptions<DbContextOptionsBuilder<MyContext>> options, ISSMService ssmService) {

    string path = Configuration.GetValue<string>("SystemsManager:ParametersPath");
    Dictionary<string, string> parameters =  ssmService.GetParametersAsync().Result;
    SqlConnectionStringBuilder builder =
        new SqlConnectionStringBuilder(Configuration.GetConnectionString("DefaultConnection"))
        {
            UserID = parameters[$"{path}/DbUser"], Password = parameters[$"{path}/DbPassword"]
        };
    options.Value.UseSqlServer(builder.ConnectionString);
}

I tried other types of IOptions, like non-generic DbContextOptionsBuilder or DbContextOptions. In all cases I get an exception at runtime that No database provider has been configured for this DbContext. It seems that options that I am setting up in Configure are not applied to the service that I am registering in ConfigureServices. How do I tie them together? I can pass MyContext - maybe there is a way to set connection string that way?

Felix
  • 9,248
  • 10
  • 57
  • 89
  • is that mandatory you have to use the AWS System manages for database details ? Yes means you need to go with another [approach](https://stackoverflow.com/a/20254520/3629732) – Rajesh Jul 11 '20 at 07:05
  • 2
    `ConfigureServices` is called _before_ `Configure`. I think you want `services.AddDbContext((provider, options) => { options.UseSqlServer(provider.GetService().GetConnectionString("DefaultConnection"), _ => {})});` or something very close – Aluan Haddad Jul 11 '20 at 07:37
  • @Rajesh - I could use something like this; but in .NET Core `source.Database` doesn't have `Connection` information, as far as I can tell. – Felix Jul 11 '20 at 07:51
  • @AluanHaddad - I am sorry; I have no idea what you are trying to say. I *know* that `ConfigureServices` is called before `Configure`. The whole point of my question is that I don't have Connection string in ConfigureServices. I register SSMService in ConfigureServices, inject it in Configure, and retrieve the credentials. But I can't configure `DbContext` in `Configure()` – Felix Jul 11 '20 at 07:55
  • 1
    What I meant was that, because the `DbContext` is created on demand by the container, if you use the `service.AddDbContext` overload that takes a factory delegate, you will have access to configuration that is added later. For example, in the factory delegate, you can resolve other services and use them to configure the `DbContext` I wrote about this here: https://stackoverflow.com/questions/47475995/net-core-injecting-and-resolving-services/47479517#47479517 – Aluan Haddad Jul 11 '20 at 07:59
  • @AluanHaddad - I understand now! I had no idea (and didn't see anywhere else) that you can get the service in `ConfigureServices()` through `provider.GetService<>()`. So, I don't need to split registration and configuration! Do you want to put it as answer? – Felix Jul 12 '20 at 19:34

0 Answers0