[EF Core] A second operation was started on this context instance before a previous operation completed.
A second operation was started on this context instance before a previous operation completed. 와 같은 문제가 발생했을 때 해결 방법에 대해 알아봅니다.
원인
A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913. 와 같은 Exception이 발생합니다.
찬찬히 설명을 보면 뭔가 멀티 스레딩 관련 오류인 것을 확인할 수 있습니다. 직접 MSDN 페이지에 들어가 보니 다음과 같은 설명이 쓰여있습니다.
Entity Framework Core는 동일한 DbContext 인스턴스에서 실행되는 여러 병렬 작업을 지원하지 않습니다. 여기에는 비동기 쿼리의 병렬 실행과 여러 스레드에서의 명시적 동시 사용이 모두 포함됩니다. 따라서 항상 await 비동기 호출을 즉시 수행하거나 병렬로 실행되는 작업에 대해 별도의 DbContext 인스턴스를 사용합니다.
비동기 메서드를 사용하면 EF Core는 비차단 방식으로 데이터베이스에 액세스 하는 작업을 시작할 수 있습니다. 그러나 호출자가 이러한 메서드 중 하나가 완료되는 것을 기다리지 않고 DbContext에 대해 다른 작업을 계속 수행하면 DbContext의 상태가 손상될 수 있습니다(가능성이 매우 높음).
결국 한 콘텍스트가 다른 비동기 호출에 의해 사용되면서 발생한 것으로 확인되었습니다.
수정
사실 저는 하나의 단일 콘텍스트를 통해 작업하려고 했기 때문에 DBContext를 AddSingleton으로 등록해 둔 상태였습니다.
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddSingleton<DBManager>();
})
.Build();
위와 같은 설명에 따라 AddSingleton을 AddTransient로 교체해 간단하게 문제를 해결할 수 있었습니다.
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddTransient<DBManager>();
})
.Build();
이제 콘텍스트를 호출하게 되면 호출마다 새로운 인스턴스가 생성되며 발생하던 문제는 해결됩니다.