DEV Community

Saumya-Ranjan-Mishra
Saumya-Ranjan-Mishra

Posted on

Understanding `IServiceScopeFactory.CreateScope()` in .NET and When to Use It

When working with dependency injection (DI) in ASP.NET Core, developers often stumble upon a tricky problem:

How do I resolve a scoped service (like DbContext) outside the normal HTTP request pipeline?

That’s where IServiceScopeFactory.CreateScope() comes into play.


The Problem

ASP.NET Core services have three main lifetimes:

  • Singleton → Created once for the entire application.
  • Scoped → Created once per HTTP request.
  • Transient → Created every time it’s requested.

Normally, in controllers or middleware, you don’t worry about scopes. ASP.NET Core automatically creates a scope for each request.

But what if you’re outside of a request? For example:

  • Running a background service (IHostedService, BackgroundService)
  • Executing a scheduled job
  • Writing a console app with the Generic Host

If you try to inject a DbContext (scoped service) directly into a singleton service like BackgroundService, it fails. The DI container doesn’t know how to manage its lifetime.


The Solution: IServiceScopeFactory.CreateScope()

IServiceScopeFactory allows you to manually create a DI scope.

Inside that scope, you can safely resolve scoped services (like DbContext) and they’ll be disposed automatically when the scope ends.

Example: Using in a Background Service

public class MyBackgroundService : BackgroundService
{
    private readonly IServiceScopeFactory _scopeFactory;

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

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using (var scope = _scopeFactory.CreateScope())
            {
                var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

                // Use DbContext safely here
                var users = await dbContext.Users.ToListAsync();
            }

            await Task.Delay(10000, stoppingToken);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Congratulations on creating your first production ready background job.
Keep learning, keep progressing..

Top comments (0)