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
publicO método é exposto publicamente e pode ser utilizado por outras camadas da aplicação.asyncIndica que o método é assíncrono, permitindo o uso deawaitpara operações de I/O sem bloqueio da thread.Task<Product>Retorna uma operação assíncrona que, ao concluir, fornece a instância deProductatualizada.UpdateAsyncNome que expressa claramente a finalidade do método: atualizar uma entidade existente de forma assíncrona.Parâmetros:
Product productEntidade 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 = defaultToken opcional que permite cancelar a operação assíncrona em curso.
Corpo do método
context.Products.Update(product)
context.Products.Update(product)Informa ao Entity Framework Core que a entidade
productdeve 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)
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
cancellationTokenpermite o cancelamento da operação antes da sua conclusão.
return product
return productRetorna a instância de
Productapó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:
Updatemarca todas as propriedades como modificadas. Para cenários de atualização parcial (partial update), recomenda-se controlar explicitamente o estado das propriedades ou utilizarAttach+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; oUpdateé 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
CancellationTokencontribui 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
publicO método é acessível externamente, permitindo sua utilização por outras camadas da aplicação, como serviços de aplicação ou controladores.asyncIndica que o método é assíncrono e utilizaawaitpara 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 deProductque foi removida.DeleteAsyncNome que expressa claramente a intenção da operação: remover uma entidade do tipoProductde forma assíncrona.Parâmetros:
Product productInstância da entidadeProductque 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 = defaultToken opcional para cancelamento da operação assíncrona.
Corpo do método
context.Products.Remove(product)
context.Products.Remove(product)Marca a entidade
productpara exclusão noDbContext.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)
await context.SaveChangesAsync(cancellationToken)Persiste no banco de dados todas as alterações pendentes no
DbContext, incluindo a exclusão da entidade marcada comoDeleted.Executa a operação de forma assíncrona.
O
cancellationTokenpermite interromper a execução da operação antes de sua finalização, caso necessário.
return product
return productRetorna a instância de
Productque 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
CancellationTokencontribui 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
publicO método é exposto publicamente, podendo ser utilizado por outras camadas da aplicação (por exemplo, serviços ou endpoints).asyncIndica que o método é assíncrono, permitindo o uso deawaitpara 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 deProductounull. O retornonullrepresenta a ausência de um produto com o identificador informado.GetByIdAsyncNome que descreve claramente a intenção: recuperar um produto específico com base no seu identificador, de forma assíncrona.Parâmetros:
int idIdentificador único do produto a ser recuperado.CancellationToken cancellationToken = defaultToken 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.Productscontexté a instância doDbContextdo Entity Framework Core.Productsé umDbSet<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()
.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)
.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çãoWHEREno SQL.O método assíncrono evita bloqueio de thread enquanto o acesso ao banco de dados ocorre.
O
cancellationTokenpermite interromper a execução da consulta antes de sua conclusão.
return await ...
return await ...Aguarda a execução assíncrona da consulta.
Retorna o objeto
Productencontrado ounullcaso 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
Idseja 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
CancellationTokenaumenta 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á usarawaitinternamente; entrega retornos sem bloquear a thread chamadora.Task<List<Product>>— tipo de retorno assíncrono: quando concluído, fornece uma lista de instânciasProduct. Aqui o método não retornanull.GetAllAsync— nome que comunica intenção: recuperar múltiplosProductde 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.Productscontextrefere-se aoDbContextdo Entity Framework Core.Productsé umDbSet<Product>representando a coleção/entidadeProductno 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()
.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)
.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
Idseja indexado no banco para eficiência.
.Skip(skip) e .Take(take)
.Skip(skip) e .Take(take)Implementam paginação:
Skip(skip)aplica um deslocamento (offset) deskipregistros.Take(take)limita a quantidade de registros retornados ao valortake.
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)
.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 ...
return await ...awaitaguarda a conclusão da tarefa assíncrona e obtém aList<Product>resultante, que é então retornada ao chamador.Observação sutil: em métodos
async,return awaitpreserva a pilha de exceção; em alguns casos onde não é necessário manipular exceções localmente, é possível retornar aTaskdiretamente (ex.:return context.Products...ToListAsync(cancellationToken);) — mas usarawaité 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
Idpara queOrderBy+Skip/Takeseja 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
cancellationTokencom timeouts e circuit-breakers em camadas superiores para resiliência.Prevenção de N+1: se
Productpossuir navegações necessárias, avalieIncludepertinente 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