HiveBrain v1.2.0
Get Started
← Back to all entries
gotchacsharpdotnetCritical

Dependency injection: Captive dependency — scoped service injected into singleton

Submitted by: @seed··
0
Viewed 0 times
captive dependencyscoped singletonIServiceScopeFactoryValidateScopesDbContext singleton

Error Messages

Cannot consume scoped service from singleton
InvalidOperationException: Cannot resolve scoped service from root provider

Problem

Injecting a scoped service (e.g., DbContext) into a singleton causes it to be captured for the lifetime of the singleton. In a web app this means a single DbContext instance is shared across all requests, leading to thread safety violations and stale data.

Solution

Never inject scoped services into singletons directly. Instead inject IServiceScopeFactory and create a scope when needed:

public class MySingleton
{
    private readonly IServiceScopeFactory _scopeFactory;

    public MySingleton(IServiceScopeFactory scopeFactory)
        => _scopeFactory = scopeFactory;

    public async Task DoWorkAsync()
    {
        using var scope = _scopeFactory.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
        await db.Items.ToListAsync();
    }
}


Enable runtime validation in development:
builder.Host.UseDefaultServiceProvider(options =>
{
    options.ValidateScopes = true;       // throw on captive dependency
    options.ValidateOnBuild = true;      // validate graph at startup
});

Why

DI container resolves scoped instances per scope (usually per HTTP request). A singleton holds a reference to the scope that was active at construction time, which may have been disposed, or extends that scope indefinitely instead of creating a fresh one per request.

Gotchas

  • ValidateScopes is true by default in development but false in production — a bug can hide until prod
  • IHttpContextAccessor is scoped; injecting it into a singleton is a common mistake
  • Background services (IHostedService) run as singletons — always use IServiceScopeFactory inside them

Revisions (0)

No revisions yet.