2

I need to register two DbContext classes in my .net core 2.1 application using the built in Ioc container. The connection details for the second context is stored in the database from the first context, so the registrations would look something like

new HostBuilder()
    .ConfigureServices((hostContext, services) =>
    {
        services
        .AddDbContext<Context1>()
        .AddDbContext<Context2>( /* Connection string from context1 here */ )
        .AddHostedService<MyHostedService>();
    });

Is there any way for me to register Context1, get the values and then use that to register Context2?

reggaemahn
  • 6,272
  • 6
  • 34
  • 59

1 Answers1

3

Use one of the overloads that will give you access to the service provider

new HostBuilder()
    .ConfigureServices((hostContext, services) =>
    {
        services
        .AddDbContext<Context1>()
        .AddDbContext<Context2>((serviceProvider, options) => {
            var context1 = serviceProvider.GetService<Context1>();
            var connectionString = /* get Connection string from context1 here */ 
            options.UseSqlServer(connectionString);
        })
        .AddHostedService<MyHostedService>();
    });

Reference AddDbContext<TContext>(IServiceCollection, Action<IServiceProvider,DbContextOptionsBuilder>, ServiceLifetime, ServiceLifetime)

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Thanks for the answer. I was looking at this option but wan't sure if I should do it because of [this line from the docs](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1#recommendations) `Avoid using the service locator pattern. For example, don't invoke GetService to obtain a service instance when you can use DI instead`. But I suppose there is no other option at this point. – reggaemahn Nov 22 '18 at 01:58
  • @jeevs noted, they also state `Like all sets of recommendations, you may encounter situations where ignoring a recommendation is required. Exceptions are rare—mostly special cases within the framework itself.` – Nkosi Nov 22 '18 at 02:01
  • @jeevs short of directly injecting the first context into the second, (which would also act like a factory), this is a special case as you have one context dependent on something that it can only get from another context. – Nkosi Nov 22 '18 at 02:02
  • Yep, agreed. Thanks again. – reggaemahn Nov 22 '18 at 02:23
  • Any idea how the `AddDbContext` method obtains a reference to the one-and-only `IServiceProvider` instance that is eventually built? Or does it cheat and create its own provider from the `IServiceCollection`? The former would be impressive, the latter disappointing. – Timo Nov 26 '18 at 15:04
  • @Timo it is a delegate (Action) that is invoked well after the provider has been built. Think of it like this. Define delegate for how to configure Dd, eventually service provider is built, and finally when ever you want to apply configuration on a newly created context you invoke the delegate with the provider. – Nkosi Nov 26 '18 at 15:10
  • @Nkosi That part I get. I'm looking for the same functionality in a different circumstance. Any idea how I can have something invoked well after the service provider has been built? I have posted a separate question explaining more clearly what I'm trying to achieve: https://stackoverflow.com/questions/53484777/access-iserviceprovider-when-using-generic-ihostbuilder – Timo Nov 26 '18 at 15:54