DBContext

Consumindo o DbContext

O DbContext, por padrão, já encapsula o Repository Pattern.

O Entity Framework Core abstrai o acesso aos dados por meio do DbSet<T>, controle de estado de entidades e implementação do padrão Unit of Work, eliminando a necessidade de criação de repositórios manuais em cenários simples.

Neste fase do projeto, o DbContext será consumido diretamente pelos endpoints para fins didáticos, demonstrando sua funcionalidade básica.

Injeção do DbContext em Minimal APIs

O AppDbContext é previamente registrado no container de injeção de dependência:

var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<AppDbContext>(options =>
{
    options.UseSqlServer(connectionString);
});

Com essa configuração, o contexto pode ser injetado diretamente nos handlers dos Minimal APIs. O runtime resolve automaticamente essa dependência para cada requisição, garantindo o isolamento apropriado do contexto.

Configuração de Rotas HTTP

No arquivo Program.cs, além do mapeamento do endpoint GET, são configuradas as rotas para POST, PUT e DELETE. As rotas permanecem consistentes (/v1/products), diferenciando-se apenas pelo verbo HTTP utilizado.

No Minimal API, a injeção do contexto aparece como parâmetro em uma função anônima:

O runtime reconhece automaticamente que o AppDbContext deve ser resolvido por injeção de dependência para cada requisição, utilizando o ciclo de vida scoped configurado.

Endpoint GET - Listagem de Produtos

Para recuperar todos os produtos, o método é tornado assíncrono e utilizado o método ToListAsync():

Componentes envolvidos:

  • Products: refere-se à propriedade DbSet<Product> definida no contexto

  • ToListAsync() executa a consulta de forma assíncrona, retornando todos os registros

  • O Entity Framework Core gerencia automaticamente a conexão, execução de comandos e mapeamento de resultados

Operações CRUD Básicas

O Entity Framework Core fornece métodos padrão para operações CRUD, pois implementa internamente o padrão Repository:

  • Criação: AddAsync()

  • Atualização: Update()

  • Remoção: Remove()

Esses métodos funcionam eficientemente porque o DbContext mantém o rastreamento do estado das entidades durante seu ciclo de vida, implementando o padrão Unit of Work.

Exemplo com Modelo Adicional (Category)

Não implementar esse exemplo.

Considerando a criação de um novo modelo Category no diretório Models:

É necessário registrar o DbSet correspondente no AppDbContext existente no diretório Data:

Com essa configuração, torna-se possível mapear um endpoint diretamente no Program.cs:

Essa abordagem demonstra-se funcional, simples e rápida de implementar.

Limitações da Abordagem Direta

No endpoint GET de produtos, seria possível aplicar otimizações diretamente:

Problemas Estruturais Identificados

Esta lógica direta apresenta limitações significativas:

  1. Acoplamento excessivo: A lógica de acesso a dados fica diretamente vinculada à camada de apresentação

  2. Reutilização impossibilitada: A implementação não pode ser compartilhada entre diferentes componentes do sistema

  3. Exposição da infraestrutura: Detalhes internos da estrutura de persistência ficam expostos

  4. Mistura de responsabilidades: Não há separação clara entre regras de negócio e lógica de apresentação

  5. Dificuldade de teste: A lógica de dados acoplada aos endpoints dificulta testes unitários

  6. Escalabilidade comprometida: Funciona adequadamente para projetos pequenos, mas não escala bem para sistemas maiores

A fronteira entre "dados" e "apresentação" torna-se difusa, comprometendo a manutenibilidade e evolução do sistema.

Decisão arquitetural

A partir deste momento, o acesso ao banco de dados não será mais realizado diretamente no Program.cs. Esta abordagem inicial, embora didática, é substituída por uma estrutura mais robusta.

Próximo Passo: Implementação de Repositórios

A partir deste momento, será realizada a implementação dos Repositórios, encapsulando:

  1. Queries complexas: Centralização de consultas específicas do domínio

  2. Regras de acesso: Controle de permissões e lógica de acesso a dados

  3. Reutilização de código: Compartilhamento de lógica entre diferentes partes do sistema

  4. Controle de complexidade: Isolamento da complexidade de acesso a dados

  5. Abstração de infraestrutura: Separação entre lógica de negócio e detalhes de persistência

A Minimal API continua sendo utilizada, e o DbContext permanece como componente fundamental. Contudo, não será mais exposto diretamente na camada de apresentação.

Agora inicia-se verdadeiramente a arquitetura de software, com a implementação dos repositórios estabelecendo uma clara separação de responsabilidades e preparando o sistema para escalabilidade e manutenibilidade de longo prazo.

Atualizado