James
James

Reputation: 553

ASP.NET Core Singleton Service created multiple times

I am working an ASP.NET Core 2.1 project where I need to register and then use a singleton service inside of Startup.ConfigureServices.

I have the following code:

public void ConfigureServices(IServiceCollection services)
{
    //....
    //....

    services.AddSingleton<IMyService,MyService>();

    var serviceProvider = services.BuildServiceProvider();

    var myService = serviceProvider.GetService<IMyService>();

    services.AddDbContext<MyDbContext>(options => options.UseMySql(myService.DBConnectionString));
}

The above code works fine for me to be able to use "MyService" inside ConfigureServices. However later in my application when I try and use MyService the constructor of MyService is being called again. Why is it not using the instance that was already created since I registered the class using AddSingleton?

EDIT: I decided to edit to add my end objective to see if maybe there is a different way to get it done. My singleton service provides access to a few settings that could come from 2 different places. One of those settings is a DB connection string. I need that connection string in ConfigureServices so I have it when I call services.AddDbContext. I also want to do some logging in the service that gets configuration settings which means I need to get the ILoggerFactory as well.

Upvotes: 4

Views: 5730

Answers (2)

Nkosi
Nkosi

Reputation: 247098

Calling BuildServiceProvider from ConfigureServices will result in an additional copy of singleton services being created.

Use another approach that defers the access to the service provider in this particular case. AddDbContext has an overload that allows for such a case, where the service provider is provided as part of the options action delegate.

//...

services.AddSingleton<IMyService, MyService>();

services.AddDbContext<MyDbContext>((serviceProvider, options) =>
    options.UseMySql(serviceProvider.GetRequiredService<IMyService>().DBConnectionString)
);

//....

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

Upvotes: 9

John Wu
John Wu

Reputation: 52240

AddSingleton tells Unity to construct it once. That "once" is in addition to any constructors that you invoke directly in your code.

If you want to re-use the instance you created, use AddInstance instead.

var serviceProvider = services.BuildServiceProvider();

var myService = serviceProvider.GetService<IMyService>();

services.AddInstance<IMyService>(myService);

services.AddDbContext<MyDbContext>(options => options.UseMySql(myService.DBConnectionString));

Upvotes: 0

Related Questions