DI019

Scoped Service Resolved From Root Provider

scoped services, known scoped framework services such as `IOptionsSnapshot<T>`, EF Core contexts from `AddDbContext(...)`, `AddDbContextFactory(...)`, `AddDbContextPool(...)`, and `AddPooledDbContextFactory(...)` including service/implementation overload self-registrations, or services whose activation graph reaches a scoped service, resolved from a root `IServiceProvider` such as ASP.NET Core `app.Services`, ASP.NET test-host `factory.Services` / `server.Services`, Generic Host `host.Services`, nullable root-provider surfaces such as `app.Services!`, or a provider returned by `BuildServiceProvider()`.

Default severity: Warning · Code fix: No

Why it matters

the default container's scope validation is designed to prevent scoped services from being resolved directly or indirectly from the root provider. Resolving them from root can fail at runtime or accidentally stretch scoped state to application lifetime.

A classroom pass only works for one lesson. Taking it home for the whole year breaks the rules.

README problem example

var app = builder.Build();
var db = app.Services.GetRequiredService<MyDbContext>();

README better pattern

var app = builder.Build();
using var scope = app.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<MyDbContext>();

No. Creating the right scope can change control flow and disposal semantics, so the fix should be chosen deliberately.

Repo sample extraction

Examples pulled from the sample app

Open full sample file

Sample app root-provider warning

    public static void BuildRootScopedResolutionExample()
    {
        var services = new ServiceCollection();
        services.AddScoped<IScopedService, ScopedService>();
        services.AddTransient<BadRootResolvedRunner>();

        using var provider = services.BuildServiceProvider();

        // DI019: Resolves a scoped service directly from the root provider.
        provider.GetRequiredService<IScopedService>();

        // DI019: Resolves a transient graph that reaches a scoped service from the root provider.
        provider.GetRequiredService<BadRootResolvedRunner>();
    }

Sample app scoped-provider pattern

    public static void GoodScopedResolutionExample()
    {
        var services = new ServiceCollection();
        services.AddScoped<IScopedService, ScopedService>();

        using var provider = services.BuildServiceProvider();
        using var scope = provider.CreateScope();

        var service = scope.ServiceProvider.GetRequiredService<IScopedService>();
        service.DoWork();
    }

Related guides

  • No problem-guide pages point here yet.