Problemas com Worker Services e Injeção de dependência no .NET?

Marcio Nizzola
3 min readNov 23, 2022

--

Problemas com Worker Services e Injeção de dependência no .NET?

Existe um problema que pode ocorrer caso você utilize um Worker Service que faça uso de Entity Framework na hora de Injetar dependências !

Ao inicializar a sua aplicação a mensagem apresentada será esta:

Cannot consume scoped service ‘nome do DbContext’ from singleton ‘CurrencyExchangeWorker.Services.ICurrencyService’.)

Mas como pode ter acontecido isso, se meu serviço foi instanciado como “Singleton” ! Veja a inicialização:

Worker Service com erro “Cannot consume scoped service”

Este problema ocorre devido ao ciclo de vida do Worker Service que é do tipo “Singleton”, porém ao utilizar o banco de dados, é gerada uma instância “Scoped”.

Só para relembrar:

Singleton

O serviço é criado uma única vez e a mesma instância é passada para todas as chamadas dele.

Scoped

Uma única instância é criada por requisição. Então se o serviço for chamado em vários lugares em uma única requisição, a mesma instância será passada.

Sendo assim, temos que fazer alguma modificação na nossa implementação padrão fornecida pelo template do Worker Service criada automaticamente.

O que fazer então ?

O problema está na forma como o Contexto do banco de dados é criado, pois o comando AddDbContext cria um contexto dentro do ciclo de vida “Scoped”, que é incompatível com o Worker Service é instanciado na forma padrão como “Singleton”.

Então vamos ajustar a nossa aplicação assim:

Primeiro, vamos ajustar o serviço dentro do ciclo de vida Scoped assim como o Contexto.

Exemplo de Worker Service modificando o ciclo de vida

Depois, dentro da classe “Worker”, vamos mudar a sua inicialização, onde ao invés de recebermos a interface do serviço, receberemos uma interface “IServiceProvider” para que possamos obter as classes depois utilizando-a.

Exemplo de correção na inicialização do Worker Service

Além disso, vemos que o método “ExecuteAsync” está chamando um outro método “DoWorkAsync”.

É aqui que a mágica acontece, vamos utilizar o nosso “ServiceProvider” para criar um “ServiceScope” e assim com este objeto, obter uma instância “Scoped” da classe do serviço “ICurrencyService”, e desta forma, poder utilizar serviços “Scoped” dentro de um Worker que é “Singleton”.

Exemplo de utilização de um serviço Scoped dentro de um Worker Singleton

E assim o problema foi resolvido !

Gostou do artigo? clique no ícone👏e me siga para ver as próximas publicações !!

Referências:

--

--

Marcio Nizzola
Marcio Nizzola

Written by Marcio Nizzola

Microsoft MVP | Software Architect na CI&T | Prof. da Etec Itu | Membro Fundador da Comunidade Itu Developers.

Responses (1)