Ответ
Scoped — это одно из трёх основных времён жизни сервиса в системе внедрения зависимостей (DI) ASP.NET Core. Scoped-сервис создаётся один раз в рамках определённой области (scope) и используется повторно всеми компонентами внутри этой области.
Ключевое применение: В веб-приложении каждый HTTP-запрос автоматически создаёт новую область. Поэтому Scoped-сервис живёт ровно столько, сколько длится обработка одного запроса.
Регистрация:
// В Program.cs или Startup.ConfigureServices
services.AddScoped<IMyService, MyService>();
services.AddScoped<ApplicationDbContext>(); // Типичный пример для EF Core
Почему это важно? Практический пример с Entity Framework Core:
Контекст БД (DbContext) по умолчанию регистрируется как Scoped. Это гарантирует, что:
- В рамках одного запроса все репозитории и сервисы работают с одним экземпляром
DbContext. - Отслеживание изменений (change tracking) работает корректно.
- В конце запроса контекст автоматически освобождается.
- Разные запросы не мешают друг другу, так как используют разные экземпляры.
Важные правила и ограничения:
-
Нельзя внедрять Scoped-сервис в Singleton-сервис. Это приведёт к тому, что Scoped-сервис будет захвачен Singleton'ом и станет вечно живущим, что вызовет проблемы (например, утечку памяти в
DbContext).// НЕПРАВИЛЬНО: services.AddSingleton<IBadService>(provider => new BadService(provider.GetRequiredService<IMyScopedService>())); // Scoped захвачен Singleton'ом -
Для явного создания области (например, в фоновой задаче или консольном приложении) используйте
IServiceScopeFactory.public class BackgroundWorker { private readonly IServiceScopeFactory _scopeFactory; public BackgroundWorker(IServiceScopeFactory scopeFactory) { _scopeFactory = scopeFactory; } public void DoWork() { using (var scope = _scopeFactory.CreateScope()) { var scopedService = scope.ServiceProvider.GetRequiredService<IMyScopedService>(); // Работаем с scopedService в изолированной области } // Здесь scopedService будет уничтожен } }
Другие времена жизни для сравнения:
- Transient: Создаётся новый экземпляр при каждом запросе сервиса. Подходит для лёгких, stateless-сервисов.
- Singleton: Создаётся один экземпляр на всё время работы приложения. Подходит для stateless-сервисов, кэшей, конфигураций.