.NET › Dependency Injection
What is the 'captive dependency' problem, and how does the DI container help catch it?
AdvancedAnswer
A captive dependency occurs when a longer-lived service (Singleton) depends on a shorter-lived service (Scoped or Transient), effectively 'capturing' that shorter-lived instance for the Singleton's entire lifetime -- defeating the purpose of the shorter lifetime and potentially causing serious bugs (like a captured DbContext being reused indefinitely across unrelated requests, sharing stale state or causing concurrency issues). ASP.NET Core's DI container detects this specific case (Singleton depending on Scoped) by default and throws an InvalidOperationException at service resolution time, unless scope validation is explicitly disabled.
builder.Services.AddSingleton<INotificationService, NotificationService>();
builder.Services.AddScoped<AppDbContext>();
// NotificationService depending on AppDbContext throws at startup/resolution:
// "Cannot consume scoped service 'AppDbContext' from singleton 'INotificationService'"
// Correct fix: inject IServiceScopeFactory into the Singleton instead
// and create scopes on demand for each unit of workReal-world example A subtle production bug where all users started seeing the same cached database results was traced to a captive dependency -- a Singleton service had captured a Scoped DbContext, which validation would have caught immediately if it hadn't been running in an environment with scope validation disabled.