Read, Update e Delete

Update

Nesta seção são apresentados os métodos responsáveis pela atualização de registros existentes da entidade Product.

Implementação: Os métodos documentados devem ser implementados na classe ProductRepository, no arquivo ProductRepository.cs, centralizando a lógica de persistência de alterações.

A validação das regras de negócio e a verificação da existência da entidade devem ser tratadas em camadas superiores, enquanto o repositório fica responsável apenas pela atualização e persistência dos dados.

   public async Task<Product> UpdateAsync(
      Product product,
      CancellationToken cancellationToken = default)
   {
      context.Products.Update(product);
      await context.SaveChangesAsync(cancellationToken);
      return product;
   }
Explicação ponto a ponto

Assinatura do método

  • public O método é exposto publicamente e pode ser utilizado por outras camadas da aplicação.

  • async Indica que o método é assíncrono, permitindo o uso de await para operações de I/O sem bloqueio da thread.

  • Task<Product> Retorna uma operação assíncrona que, ao concluir, fornece a instância de Product atualizada.

  • UpdateAsync Nome que expressa claramente a finalidade do método: atualizar uma entidade existente de forma assíncrona.

  • Parâmetros:

    • Product product Entidade contendo os dados atualizados que devem ser persistidos no banco de dados. Presume-se que a entidade possua uma chave primária válida.

    • CancellationToken cancellationToken = default Token opcional que permite cancelar a operação assíncrona em curso.


Corpo do método

context.Products.Update(product)

  • Informa ao Entity Framework Core que a entidade product deve ser tratada como modificada.

  • O EF Core:

    • Anexa a entidade ao DbContext, caso ainda não esteja sendo rastreada.

    • Define o estado da entidade como Modified.

  • Todos os campos mapeados da entidade são considerados passíveis de atualização, independentemente de terem sido alterados ou não.


await context.SaveChangesAsync(cancellationToken)

  • Persiste no banco de dados todas as alterações pendentes no DbContext, incluindo a atualização da entidade.

  • Executa a operação de forma assíncrona.

  • O cancellationToken permite o cancelamento da operação antes da sua conclusão.


return product

  • Retorna a instância de Product após a atualização.

  • O objeto retornado reflete o estado em memória no momento pós-SaveChangesAsync (incluindo valores atualizados pelo banco, se houver, como triggers ou colunas calculadas, desde que estejam configuradas para isso).


Considerações e boas práticas

  • Atualização parcial: Update marca todas as propriedades como modificadas. Para cenários de atualização parcial (partial update), recomenda-se controlar explicitamente o estado das propriedades ou utilizar Attach + Entry.Property(...).IsModified.

  • Concorrência: utilize optimistic concurrency (ex.: RowVersion) para evitar sobrescritas silenciosas em ambientes concorrentes.

  • Validação: valide os dados da entidade antes de persistir alterações, preferencialmente em camada de domínio ou aplicação.

  • Rastreamento: se a entidade foi carregada previamente com AsNoTracking, ela estará desanexada; o Update é adequado para reanexar nesse cenário, mas deve ser usado com cautela.

  • Exceções: falhas de integridade, regras de negócio ou conflitos de concorrência devem ser tratadas adequadamente em camada superior.

  • Cancelamento: a propagação do CancellationToken contribui para maior controle e robustez do fluxo assíncrono.

Delete

Nesta seção são apresentados os métodos responsáveis pela remoção de registros da entidade Product.

Implementação: Os métodos documentados devem ser implementados na classe ProductRepository, no arquivo ProductRepository.cs, mantendo a responsabilidade pela exclusão concentrada na camada de acesso a dados.

Cabe às camadas de aplicação ou domínio decidir se a remoção será física ou lógica, enquanto o repositório executa a estratégia definida.

Explicação ponto a ponto

Assinatura do método

  • public O método é acessível externamente, permitindo sua utilização por outras camadas da aplicação, como serviços de aplicação ou controladores.

  • async Indica que o método é assíncrono e utiliza await para operações de I/O, evitando bloqueio da thread durante o acesso ao banco de dados.

  • Task<Product> O método retorna uma tarefa assíncrona que, ao ser concluída, fornece a instância de Product que foi removida.

  • DeleteAsync Nome que expressa claramente a intenção da operação: remover uma entidade do tipo Product de forma assíncrona.

  • Parâmetros:

    • Product product Instância da entidade Product que será excluída do banco de dados. Presume-se que a entidade já esteja associada ao contexto (ou ao menos contenha a chave primária).

    • CancellationToken cancellationToken = default Token opcional para cancelamento da operação assíncrona.


Corpo do método

context.Products.Remove(product)

  • Marca a entidade product para exclusão no DbContext.

  • O Entity Framework Core altera o estado da entidade para Deleted.

  • Nenhuma operação é executada no banco de dados neste momento; a exclusão só ocorre quando SaveChangesAsync é chamado.


await context.SaveChangesAsync(cancellationToken)

  • Persiste no banco de dados todas as alterações pendentes no DbContext, incluindo a exclusão da entidade marcada como Deleted.

  • Executa a operação de forma assíncrona.

  • O cancellationToken permite interromper a execução da operação antes de sua finalização, caso necessário.


return product

  • Retorna a instância de Product que foi removida.

  • Embora a entidade não exista mais no banco de dados, o objeto ainda existe em memória e pode ser utilizado para:

    • Confirmação da operação.

    • Registro em logs.

    • Retorno em respostas da API (quando apropriado).


Considerações e boas práticas

  • Validação prévia: recomenda-se validar se a entidade existe antes da exclusão, especialmente quando o método é exposto diretamente a camadas superiores.

  • Rastreamento da entidade: a entidade deve estar anexada ao DbContext. Caso contrário, o EF Core pode anexá-la implicitamente no momento da remoção com base na chave primária.

  • Concorrência: em cenários concorrentes, considere o uso de concurrency tokens (ex.: RowVersion) para evitar exclusões inconsistentes.

  • Exclusão lógica (soft delete): dependendo do domínio, pode ser preferível aplicar soft delete (marcação de status) em vez de exclusão física.

  • Tratamento de exceções: falhas de integridade referencial (FK) ou outras restrições do banco devem ser tratadas em camada apropriada.

  • Cancelamento: a propagação do CancellationToken contribui para maior robustez e controle da operação.

Read

Nesta seção são apresentados os métodos responsáveis pela leitura de dados da entidade Product.

Implementação: Os métodos documentados devem ser implementados na classe ProductRepository, localizada no arquivo ProductRepository.cs, que é responsável pelo acesso a dados da entidade.

Esses métodos devem encapsular exclusivamente a lógica de consulta ao banco de dados, utilizando operações assíncronas do Entity Framework Core e evitando o rastreamento de entidades sempre que possível.

GetById

Explicação ponto a ponto
  • public O método é exposto publicamente, podendo ser utilizado por outras camadas da aplicação (por exemplo, serviços ou endpoints).

  • async Indica que o método é assíncrono, permitindo o uso de await para operações de I/O sem bloquear a thread.

  • Task<Product?> O método retorna uma tarefa assíncrona que, ao ser concluída, fornece uma instância de Product ou null. O retorno null representa a ausência de um produto com o identificador informado.

  • GetByIdAsync Nome que descreve claramente a intenção: recuperar um produto específico com base no seu identificador, de forma assíncrona.

  • Parâmetros:

    • int id Identificador único do produto a ser recuperado.

    • CancellationToken cancellationToken = default Token opcional que permite cancelar a operação assíncrona, normalmente propagado a partir da requisição ou de políticas de timeout.


Corpo do método

context.Products

  • context é a instância do DbContext do Entity Framework Core.

  • Products é um DbSet<Product>, representando a coleção de produtos mapeada para uma tabela no banco de dados.

  • A partir desse ponto, a consulta LINQ é construída e posteriormente traduzida em SQL pelo EF Core.


.AsNoTracking()

  • Desabilita o rastreamento de alterações (change tracking) para a entidade retornada.

  • Benefícios principais:

    • Melhor desempenho para consultas de leitura.

    • Menor consumo de memória.

  • É apropriado neste caso, pois o objetivo do método é apenas ler dados, não modificá-los.


.FirstOrDefaultAsync(x => x.Id == id, cancellationToken)

  • Executa uma consulta que retorna o primeiro registro que satisfaz a condição x.Id == id.

  • Caso nenhum registro seja encontrado, retorna null.

  • Características importantes:

    • A cláusula x => x.Id == id é traduzida em uma condição WHERE no SQL.

    • O método assíncrono evita bloqueio de thread enquanto o acesso ao banco de dados ocorre.

    • O cancellationToken permite interromper a execução da consulta antes de sua conclusão.


return await ...

  • Aguarda a execução assíncrona da consulta.

  • Retorna o objeto Product encontrado ou null caso não exista um registro correspondente.

  • Mantém o fluxo assíncrono e facilita o tratamento de exceções no chamador.


Considerações e boas práticas

  • Unicidade do identificador: pressupõe-se que Id seja chave primária ou possua restrição de unicidade no banco de dados.

  • Uso de FirstOrDefaultAsync: adequado quando se espera zero ou um resultado. Caso a inexistência seja considerada um erro de domínio, a validação deve ocorrer em camada superior.

  • Índices: recomenda-se índice (normalmente já existente como chave primária) para garantir eficiência na busca por Id.

  • AsNoTracking: ideal para leitura; deve ser removido se o objeto precisar ser atualizado e persistido pelo mesmo DbContext.

  • Cancelamento: sempre propagar o CancellationToken aumenta a previsibilidade e resiliência da aplicação, especialmente em cenários de alta carga ou APIs HTTP.

GetAll

Explicação ponto a ponto

Assinatura do método

  • public — acesso público; disponível para chamadores externos à classe.

  • async — indica que o método é assíncrono e poderá usar await internamente; entrega retornos sem bloquear a thread chamadora.

  • Task<List<Product>> — tipo de retorno assíncrono: quando concluído, fornece uma lista de instâncias Product. Aqui o método não retorna null.

  • GetAllAsync — nome que comunica intenção: recuperar múltiplos Product de forma assíncrona.

  • Parâmetros:

    • int skip = 0 — número de registros a pular (offset). Tem valor padrão 0.

    • int take = 25 — número máximo de registros a retornar (limit). Valor padrão 25.

    • CancellationToken cancellationToken = default — permite cancelar a operação de I/O; valor padrão sem token.


context.Products

  • context refere-se ao DbContext do Entity Framework Core.

  • Products é um DbSet<Product> representando a coleção/entidade Product no modelo e mapeada ao banco de dados.

  • A consulta construída a seguir será traduzida pelo EF Core para uma instrução SQL executada no banco.


.AsNoTracking()

  • Desabilita o change tracking do EF Core para as entidades retornadas.

  • Benefícios:

    • Menor consumo de memória.

    • Melhor desempenho em consultas apenas de leitura.

  • Uso apropriado quando não se pretende modificar as entidades e persistir essas alterações pelo mesmo DbContext.


.OrderBy(x => x.Id)

  • Afeta a ordenação dos resultados pelo identificador Id.

  • Importante para garantir ordenação determinística antes de aplicar Skip/Take (paginação consistente).

  • Recomenda-se que Id seja indexado no banco para eficiência.


.Skip(skip) e .Take(take)

  • Implementam paginação:

    • Skip(skip) aplica um deslocamento (offset) de skip registros.

    • Take(take) limita a quantidade de registros retornados ao valor take.

  • Ordem e consistência:

    • A paginação só é confiável se houver uma ordenação estável (por isso o OrderBy é obrigatório).

  • Observações operacionais:

    • Offsets grandes podem degradar performance em alguns SGBDs; para grandes conjuntos considere paginação baseada em cursores/seek (ex.: WHERE Id > lastId LIMIT n).


.ToListAsync(cancellationToken)

  • Executa a consulta de forma assíncrona e materializa os resultados em uma List<Product>.

  • Recebe o cancellationToken, permitindo cancelar a execução do comando no banco.

  • Retorna Task<List<Product>>, que é await-ado no método.


return await ...

  • await aguarda a conclusão da tarefa assíncrona e obtém a List<Product> resultante, que é então retornada ao chamador.

  • Observação sutil: em métodos async, return await preserva a pilha de exceção; em alguns casos onde não é necessário manipular exceções localmente, é possível retornar a Task diretamente (ex.: return context.Products...ToListAsync(cancellationToken);) — mas usar await é claro e aceitável.


Considerações e boas práticas

  • Validação de parâmetros: impor limites em take (ex.: máximo 100) evita consultas excessivas e abusos acidentais.

  • Índices: garanta índice em Id para que OrderBy + Skip/Take seja eficiente.

  • AsNoTracking é adequado aqui por se tratar de leitura; se for necessária edição subsequente, remova-o.

  • Paginação em grandes tabelas: para offsets muito grandes, prefira paginação por cursores para melhor desempenho e consistência.

  • Timeout e limites: combine cancellationToken com timeouts e circuit-breakers em camadas superiores para resiliência.

  • Prevenção de N+1: se Product possuir navegações necessárias, avalie Include pertinente para evitar consultas adicionais.

  • Segurança: verifique políticas de autorização onde aplicável antes de expor listas sensíveis.


Com isso finaliza a implementação do repositório de produtos

Atualizado