-
[EntityFramework Core] Worker 서비스에 DBContext DI 설정에 의한 System.AggregateException 오류 발생시 처리.NET/개념 및 유용한 팁 2021. 2. 18. 22:38반응형
Worker 서비스 개발 중 아래와 같은 오류를 접하였다.
System.AggregateException: 'Error while validating the service descript(Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType:
Cannot consume scoped serviceASP.NET Core에선 나오지 않았던 오류인데 대충 해석하면 Singleton lifecycle 기반으로 동작하는 BackgroundService Worker에 Scoped 으로 설정된 서비스는 의존성 주입(Dependency Injection, DI)을 못한다는 것으로 풀이된다.
* 의존성 주입 생명주기에 대해선 심재운님의 블로그 글을 참조하자.
ASP.NET Core에서 사용할땐 Controller는 기본적으로 Scoped 로 동작했기 때문에 별 생각 없었는데 Worker 는 다르더라. 해결하려면 아래 두 가지 방법이 있다.
1. DBContext를 Singleton으로 사용
이 경우는 아래와 같이 코드를 서비스 등록위치(대게 Program.cs)에 아래와 같이 코드를 작성하면 된다.
services.AddDbContext<MyDBContext>(option => option.UseMySql(configuration.GetConnectionString("{DB연결문자열이름}")), ServiceLifetime.Singleton, ServiceLifetime.Singleton) // singleton 으로 옵션 설정
이렇게 하면 Worker의 생성자에 직접적으로 Dbcontext 객체를 파라메터로 받아 사용할 수 있다.
private readonly ILogger<MyWorker> _logger; private readonly IServiceScopeFactory _scopeFactory; private readonly MyDBContext _db; public MyWorker(ILogger<RegistWorker> logger, MyDBContext db) { _logger = logger; _scopeFactory = scopeFactory; _db = db; }
비교적 간단하게 사용할 수 있지만, 큰 문제점이 있다. 프로젝트에 다수의 Worker에서 동시에 사용할 수 없다. 사용하게되면 아래와 같은 오류를 만나게 된다.
DBContextPool을 사용하면 되지 않을까 싶었지만, 아쉽게도 DBContextPool은 Singleton 관련 옵션을 찾을 수 없었다.
그래도 방법이 없는건 아니다.
2. Worker에서 Scoped 적용
Scoped로 동작한다고하니, Scoped로 설정하면 된다. Worker 서비스를 아래와 같이 수정하면 된다.
private readonly ILogger<MyWorker> _logger; private readonly IServiceScopeFactory _scopeFactory; public MyWorker(ILogger<MyWorker> logger, IServiceScopeFactory scopeFactory) { _logger = logger; _scopeFactory = scopeFactory; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { using var scope = _scopeFactory.CreateScope(); using var db = scope.ServiceProvider.GetRequiredService<MyDBContext>(); *** db 사용 관련 코드 *** }
이 경우는 DBContextPool로 DI 처리가 가능하므로, 각 Worker에서 필요에 따라 DBContext를 할당받아 사용할 수 있다. 현재 개발 진행중인 프로젝트도 2번째 방법으로 개발하고 있다.
반응형'.NET > 개념 및 유용한 팁' 카테고리의 다른 글