Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

[Dúvida] Usando EntityFramework, uma mesma conexão com um unico banco de dados mas com multiplos comtextos

Bom dia, tudo bom ?

queria tirar uma duvida, tenho uma aplicação com Webapi com dotnet 6.0, esta separada em camadas, exp api com controller somente e DI gerenciamento de conexão e outras 20 classlibs que trabalham independentes,

nessa class Libs cada uma deles tem um contexto separado que utilização o conexão gerada pelo gerenciador, queria ver se consigo fazer isso com o EntityFramework, pois antes de tentar implementar alguma modificação tentei fazer um teste mas ele me retorou informando que tem um um objeto no banco de dados com o nome, lembrando que hoje o entityfremework é serve somente para poder fazer a relação de para com o que está no banco, não utilizamos ele para criar a conexão e gerenciar todo o processo, e nem para criar ou alterar as tabelas, nesse caso ele ainda não irá fazer esse gerenciamento seria somente para poder criar uma conexão mas nesse caso eu teria mais de 30 contextos, o que mudaria seria somente as tabelas de referencia pois o bando é o mesmo para todos.

queria ver se esse processo está correto, nocaso eu teria que ter sometne uma conexão com o banco de dados, servido pro alguma classe da minha aplicação, e os outros contextos somente devem utilizar somente e unicamente essa conexão para toda a aplicação, teria alguma forma de fazer esse processo

5 respostas

Olá Erick.

Tudo bem?

Pelo que entendi da sua dúvida, você está trabalhando em uma aplicação .NET 6 com uma arquitetura dividida em camadas e gostaria de saber se é possível utilizar múltiplos contextos do Entity Framework para acessar um único banco de dados, mas com diferentes tabelas de referência para cada contexto. É isso mesmo, né?

Sim, é possível fazer isso no Entity Framework. Você pode definir múltiplos contextos de dados em sua aplicação, cada um configurado para operar com diferentes partes do seu banco de dados. Isso pode ser útil em aplicações grandes e complexas, onde você quer isolar certas partes do banco de dados para diferentes módulos ou bibliotecas da sua aplicação.

Aqui está um exemplo básico de como você pode configurar isso:

  1. Defina os contextos: Crie diferentes classes de contexto para cada parte do banco de dados que você quer isolar. Por exemplo:

    public class ContextoA : DbContext
    {
        public DbSet<EntidadeA> EntidadesA { get; set; }
    
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("sua-string-de-conexao");
        }
    }
    
    public class ContextoB : DbContext
    {
        public DbSet<EntidadeB> EntidadesB { get; set; }
    
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("sua-string-de-conexao");
        }
    }
    
  2. Configure a injeção de dependência: No seu Startup.cs ou onde você configura os serviços, adicione os contextos ao sistema de injeção de dependência:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ContextoA>();
        services.AddDbContext<ContextoB>();
    }
    
  3. Use os contextos nos seus controllers ou serviços: Agora você pode injetar e usar esses contextos de forma independente em diferentes partes da sua aplicação.

    public class MeuServico
    {
        private readonly ContextoA _contextoA;
        private readonly ContextoB _contextoB;
    
        public MeuServico(ContextoA contextoA, ContextoB contextoB)
        {
            _contextoA = contextoA;
            _contextoB = contextoB;
        }
    
        public void AlgumaOperacao()
        {
            // Use _contextoA e _contextoB conforme necessário
        }
    }
    

Lembre-se de que, embora você possa ter múltiplos contextos, cada contexto gerencia sua própria conexão com o banco de dados. Se você precisa que todos os contextos compartilhem exatamente a mesma conexão física (o que é menos comum e pode ser mais complexo de gerenciar corretamente), você teria que gerenciar a conexão em um nível mais baixo.

Espero ter entendido e conseguido ajudar. Qualquer dúvida manda aqui. Bons estudos.

Boa noite Renan, tudo bom?

Seria quase isso, a unica diferença e que somente um contexto realizaria a conexão com o banco de dados e os demais estenderiam ele para que todos fiquem na mesma conexão e possam compartilhar dados e processos, pois teria casos em que algum desses contextos devem se enchergar para participar de uma mesma transação e transitar dados de acesso e gerenciamento de conexão.

esse e um caso que tenho aqui onde alem de conectar com o bando ele deve gerenciar uma tabela específica para validar tempode acesso se tem algum processo em transação caso tenha, mesmo que o usuario nao esteja utilizando o sistema ele tem que manter a conexão ate finalizar o processo, e juntamente com esse processo uma classe para cuidar somente das transactions, toda transação aberta ten que fazer um alteracao no banco.

complicado nao, estou perdido nesse caso

Entendi melhor agora, Erick. Parece que você está lidando com uma situação em que apenas um contexto deve gerenciar a conexão com o banco de dados, enquanto os outros contextos devem compartilhar essa mesma conexão para poderem interagir entre si e participar de transações conjuntas, correto?

Essa é uma situação um pouco mais complexa. Aqui está uma abordagem na teoria, que você pode considerar:

  1. Contexto principal com a conexão: Crie um contexto principal que será responsável por gerenciar a conexão com o banco de dados e quaisquer tabelas específicas necessárias para o controle de transações ou processos globais. Este contexto será responsável por manter a conexão ativa enquanto necessário.

  2. Contextos secundários estendendo o principal: Os outros contextos da sua aplicação devem estender este contexto principal, em vez de implementarem diretamente DbContext. Isso permite que eles compartilhem a mesma conexão e possam interagir com os dados gerenciados pelo contexto principal.

  3. Gerenciamento de transações: Implemente uma lógica para gerenciamento de transações que permita que todos os contextos participem de uma transação conjunta quando necessário. Isso pode envolver a coordenação entre os diferentes contextos para garantir que todas as operações relacionadas à transação sejam tratadas corretamente.

  4. Classe para cuidar das transactions: Crie uma classe dedicada para gerenciar as transações, garantindo que todas as transações abertas sejam devidamente tratadas e finalizadas conforme necessário. Esta classe pode ser responsável por iniciar, confirmar ou reverter transações, dependendo das operações realizadas pelos diferentes contextos.

  5. Validação do tempo de acesso e processos em transação: Implemente a lógica necessária dentro do contexto principal para validar o tempo de acesso e verificar se existem processos em transação. Isso pode envolver consultas à tabela específica que você mencionou para determinar se uma conexão precisa ser mantida ativa para um determinado processo.

  6. Testes e validação: Certifique-se de testar bastante essa abordagem para garantir que funcione conforme esperado e que todas as operações de transação sejam tratadas corretamente.

Essa abordagem pode ser um pouco mais complexa de implementar, mas deve permitir que você alcance o comportamento desejado, mantendo todos os contextos da sua aplicação compartilhando a mesma conexão com o banco de dados principal.

Perfeito, mutio obrigado, processo já implementado na refatoração que fiz. Tenho somente mais uma dúvida sobre esse caso.

Exp:

Tenho meu processo implementado ContextoPai -> realizando a conexão e sendo injetado com a connectionString ContextoFilho1, ContextoFilho2, ContextoFilho3, ContextoFilho3, ContextoFilho4 -> estendento o pai

Classe que gerencia a transação -> com todos os processo de regenciamento de conexão etc...

tenho em um processo a abertura de um transação, e descobri que um dos processos que ela realiza dentro do gerenciamente de conexão, chama outro processo que por sua vez abre outr transação, ou seja nesse caso tenho uma transação dentro de outra, queria ver se isso pode ocasionar algum problema?

solução!

Sim, a situação que você descreve, com uma transação dentro de outra, pode potencialmente causar problemas, dependendo de como as transações são gerenciadas e do comportamento esperado da sua aplicação.

Quando você aninha transações, a transação interna pode ser afetada pelo estado da transação externa. Por exemplo, se a transação externa for revertida, a transação interna também será revertida, mesmo que ela tenha sido bem-sucedida até aquele ponto. Isso pode levar a resultados inesperados e possíveis inconsistências no banco de dados.

Além disso, aninhar transações pode aumentar a complexidade do seu código e tornar mais difícil entender e manter o comportamento de transação da sua aplicação.

Em geral, é importante considerar cuidadosamente a necessidade de aninhar transações e garantir que o comportamento seja claro e previsível. Se possível, tente evitar aninhar transações sempre que for possível. Em vez disso, busque projetar sua lógica de transação de forma que ela possa ser executada em uma única transação de nível superior, se isso for adequado para os requisitos da sua aplicação.

Se você realmente precisa aninhar transações, certifique-se de entender completamente as implicações disso e teste cuidadosamente para garantir que o comportamento seja consistente e correto em todas as situações possíveis.