Injecting scoped service in a singleton service

If you want to use a scoped service in a singleton service in a Asp.Net Core MVC project you can’t inject it via constructor injection. You’ll have to create a scope when needed. In my case I needed to use a DbContext service regisered with .AddDbContext as a scoped service in startup.cs into a hosted service.

First you have to create a service inheriting of IHostedService (Microsoft.Extensions.Hosting) with the following code:


public abstract class HostedService : IHostedService
{
// Example untested base class code kindly provided by David Fowler: https://gist.github.com/davidfowl/a7dd5064d9dcf35b6eae1a7953d615e3

private Task _executingTask;
private CancellationTokenSource _cts;

public Task StartAsync(CancellationToken cancellationToken)
{
// Create a linked token so we can trigger cancellation outside of this token's cancellation
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

// Store the task we're executing
_executingTask = ExecuteAsync(_cts.Token);

// If the task is completed then return it, otherwise it's running
return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
}

public async Task StopAsync(CancellationToken cancellationToken)
{
// Stop called without start
if (_executingTask == null)
{
return;
}

// Signal cancellation to the executing method
_cts.Cancel();

// Wait until the task completes or the stop token triggers
await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken));

// Throw if cancellation triggered
cancellationToken.ThrowIfCancellationRequested();
}

// Derived classes should override this and execute a long running method until
// cancellation is requested
protected abstract Task ExecuteAsync(CancellationToken cancellationToken);
}

The following code in the singleton service works for me:

public class AnyService
{
    private readonly IServiceScopeFactory _scopeFactory;

    public AnyService(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    public void Execute()
    {
        using (var scope = _scopeFactory.CreateScope())
        {
            var dbContext = scope.ServiceProvider.GetRequiredService<MyDbContext>();
            
        }
    }
    
}

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert