Singleton, Scoped e Transient: tudo o que você precisa saber (e algumas coisas que é bom evitar)

แชร์
ฝัง
  • เผยแพร่เมื่อ 20 ม.ค. 2025

ความคิดเห็น • 18

  • @marcossantosoliveira7431
    @marcossantosoliveira7431 3 ปีที่แล้ว +5

    Parabens Cara, continue trazendo bons conteúdos para nós pois sua didática é muito boa!

    • @OkazakiAndre
      @OkazakiAndre  3 ปีที่แล้ว

      Valeu Marcos, grande abraço!!

  • @sandrogeraldo3881
    @sandrogeraldo3881 2 ปีที่แล้ว

    Obrigado pela aula. Material de primeira qualidade.

    • @OkazakiAndre
      @OkazakiAndre  2 ปีที่แล้ว

      Valeu Sandro, fico feliz por ter ajudado. Abraço!

  • @rafaelferreiraalves2258
    @rafaelferreiraalves2258 ปีที่แล้ว

    Obrigado pelo vídeo.

  • @OkazakiAndre
    @OkazakiAndre  3 ปีที่แล้ว +4

    Estava pronunciando "scuped", mas pesquisei agora e o certo é "scouped"... Beleza, já aprendi algo novo hoje rsrs

  • @leantruts
    @leantruts ปีที่แล้ว

    Cara, com seu exemplo consegui entender a diferença entre Scoped e Transient. Singleton é bem definido, mas os outros dois tipos de ciclo de vida da aplicação me geravam confusão, eu não conseguia entender a diferença. Obrigado!

    • @OkazakiAndre
      @OkazakiAndre  ปีที่แล้ว

      Aí sim! É o tipo de recurso que não faz diferença na sua vida até você descobrir como funciona. Abraço!

  • @vagnersantos2686
    @vagnersantos2686 2 ปีที่แล้ว +1

    Salve Andre!!!
    Eu fiquei com uma duvida.
    Em uma aplicação Web, o mais correto é criar a conexão com banco Scuped ou singleton?
    Eu acredito que usar o scuped traria o risco de estouro do pool de conexões a medida que vários usuários façam as requisições na minha api, no entanto, abrir a conexão e criar a conexão são coisas distintas.
    Atualmente, eu crio a conexão com singleton, e fecho a cada execução no banco, o dapper faz isso por padrão, mas a instancia da conexão está sempre la enquanto a aplicação está de pé e garanto com isso que o pool não estoure, mas assim corro o risco de criar lock no banco.
    Qual sua recomendação?

    • @OkazakiAndre
      @OkazakiAndre  2 ปีที่แล้ว +2

      Tem várias coisas para pensar aí, vou ter dar um resumo e você pode ler os detalhes mais abaixo se estiver com paciência:
      - Não sei se influencia tanto assim se a sua classe de conexão é Singleton ou Scoped, depende do volume de requisições.
      - Eu sempre uso Scoped para a classe de conexão com o banco, mas já usei Singleton em sistemas com uso razoável para o padrão corporativo e nunca tive problemas.
      - Se você está com dúvida, é mais fácil montar um cenário de load test e avaliar o resultado. Só toma cuidado para não superestimar o load test, é muito fácil se perder em tecnicidades que não geram valor real para o negócio.
      Abraço!!
      Agora a resposta mais detalhada:
      1) Entre Scoped e Singleton, geralmente é melhor escolher o Scoped. Singleton é um pattern problemático em ambientes multithread porque você sempre vai ter o risco da concorrência. Do ponto de vista da arquitetura, são raros os casos onde usar Singleton é bom, porque ele também tem várias desvantagens e costuma gerar problemas difíceis de detectar em ambiente de testes. Acho que a facilidade atual do .Net para implementar esse pattern às vezes faz os devs olharem para ele de um jeito descuidado.
      2) Mesmo com esses problemas, em muitos cenários não faz tanta diferença na prática usar Scoped ou Singleton. Se a sua aplicação tem uma quantidade baixa de requisições por minuto, a chance de ter problema é pequena. Veja, não estou dizendo que se tem pouco acesso podemos fazer de qualquer jeito e sem entender para quê serve cada recurso (embora isso seja bem comum em muitas empresas). É só para deixar claro que, quanto menos crítica é a aplicação, menor é o impacto das suas decisões técnicas.
      3) O controle do pool de conexões está no driver, e não na sua aplicação. É claro que se você deixar várias conexões abertas ao mesmo tempo vai dar ruim, mas só o fato de dar o dispose (com using mesmo) já é suficiente. Na próxima vez que você pedir uma conexão, o driver vai procurar por uma que esteja disponível, e só vai criar uma nova se for necessário e possível.
      4) O lock acontece dentro do banco, e não na sua aplicação. É o mesmo problema do Singleton: o dado está em um local centralizado, e tem situações onde ele não pode ser alterado ou acessado porque já está em uso, e o banco controla isso com os locks (é uma explicação bem resumida, tem vários tipos de locks dependendo do banco). Na sua aplicação o máximo que pode acontecer é não ter conexões disponíveis no pool e ele não pode mais criar, nesse caso vai enfileirar. Um outro impacto que a sua aplicação pode causar é ocupar todas as conexões que o banco suporta, nesse caso também vai enfileirar.
      5) Eu tento tomar cuidado com essas questões de "qual é a implementação mais correta" ou "qual comando é mais rápido", porque eu curto muito essa parada e acabo perdendo tempo com detalhes que são inúteis em algumas situações. Código de alta perfomance custa mais caro, e às vezes a sua aplicação não exige tanto quanto você imagina. Agora, se o seu caso já é um problema real e você precisa encontrar a melhor solução, parte para um load test. É um tipo de teste que exige mais análise e conhecimento da aplicação, mas quando aplicado do jeito certo fornece uma visão muito clara do problema.

    • @vagnersantos2686
      @vagnersantos2686 2 ปีที่แล้ว

      @@OkazakiAndre
      Muito boa sua explicação, foi com certeza esclarecedora.
      No meu caso, acredito que eu tenha superestimado o problema.
      Vou usar o scoped sem medo, porque minha aplicação nao terá tantas requisições a mesma base, por mais que ela cresça, devido a arquitetura que fiz na aws ec2 onde ela vai ser hospedada.
      Obrigado pela tempo em me responder.

  • @HernandesJunio
    @HernandesJunio 3 ปีที่แล้ว +1

    André, tudo bem? Gostei muito do que foi abordado, pois realmente não prestamos muito a atenção nesses pequenos detalhes que podem ser cruciais para o desempenho da aplicação. Eu ainda não tenho muito conhecimento do .Net Core, mas já estou me familiarizando com esses novos recursos aos poucos.

    • @OkazakiAndre
      @OkazakiAndre  3 ปีที่แล้ว

      Boa! O esquema é ir pro campo e experimentar. Abraço!

  • @vinifran1000
    @vinifran1000 3 ปีที่แล้ว +3

    Olá Andre, não sei se pulei alguma parte do video que vc falou sobre, mas se eu tento injetar uma dependência scoped em uma classe singleton tomariamos um InvalidOperationException no startUp e a aplicação nem subiria, o que me parece correto! Não teria sentido permitir uma operação dessas já que uma instancia scoped amarrada a uma instancia singleton se tornaria 'singleton' de qualquer maneira. Pelo seu exemplo me parece que isso não está acontecendo. Saberia me dizer onde que eu estou comendo bola? Você colocou algum tratamento pra essa exceção durante o start up da aplicação para seguir com a execução da mesma?

    • @OkazakiAndre
      @OkazakiAndre  3 ปีที่แล้ว +2

      Não tem tratamento de erro, inclusive não é boa prática no startup. O ideal é testar pra ter certeza e não estou perto do computador agora, mas acredito que em situações como essa que vc citou não ocorre erro no runtime pq na prática a injeção é possível, só não vai se comportar do jeito certo (tem até um disclaimer sobre isso na documentação do .Net). No caso do singleton e scoped isso é mais evidente, mas o problema em si seria o mesmo se fosse scoped e transient. Abraço!!

    • @vinifran1000
      @vinifran1000 3 ปีที่แล้ว +1

      @@OkazakiAndre olá valeu pelo retorno. Bom eu reproduzi facilmente a exceção. Essa é a mensagem lançada na exceção:
      " System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: Project.ISingletonClass Lifetime: Singleton ImplementationType: Project.SingletonClass': Cannot consume scoped service 'Project.ScopedClass' from singleton 'Project.ISingletonClass'."
      A run time lança essa exceção durante a validação das classes que estamos injetando, isso ocorre no WarmUp da Aplicação. E na mensagem da exceção está explícito que uma classe scoped não pode ser consumida por uma classe singleton. Nota: estou usando net5.0 e não. NetCore 3, será que tivemos uma mudança no .net5.0?

    • @OkazakiAndre
      @OkazakiAndre  3 ปีที่แล้ว +2

      @@vinifran1000 Tive que dar uma olhada no código pra lembrar dessa parada rsrs. Essa validação só acontece quando a variável de ambiente do ASP Net Core está setada como "Development", pois nesse caso o web host executa algumas validações adicionais. Esse issue no repo da Microsoft fala sobre isso: github.com/dotnet/extensions/issues/2113
      Se vc olhar o código dessa aula no GitHub (que é .Net 5, link na descrição), vai ver que a variável de ambiente para o Swagger está setada como "test", justamente pra fazer a aplicação subir e poder mostrar que o maior ciclo de vida prevalece.
      Acho que eu falo sobre isso em algum ponto do vídeo, mas confesso que não procurei agora pq tava editando um vídeo novo hj e já enjoei de me olhar na tela rsrs.
      Valeu por mencionar o ponto e abrir a discussão, pode ajudar outras pessoas. Grande abraço!!

    • @vinifran1000
      @vinifran1000 3 ปีที่แล้ว +1

      @@OkazakiAndre Eu que agradeço pela atenção! Não tinha me ligado que podia ser por conta da variável estar como Development no profile que uso! MInha duvida agora está sanada! haha Abraços Andre