marcelohnq / costumer-api

API application for clients, products, and payments. | ASP.NET, API, GitHub Actions, Unit Tests, Integration Tests, TestContainers, Coverage
2 stars 0 forks source link

Parte2Controller #2

Closed marcelohnq closed 7 months ago

marcelohnq commented 7 months ago

Essa API deveria retornar os produtos cadastrados de forma paginada. O usuário informa a página (page) desejada e o sistema retorna os 10 itens da mesma. O problema é que não importa qual número de página é utilizado: os resultados estão vindo sempre os mesmos. E não apenas os 10.

Você precisa portanto:

marcelohnq commented 7 months ago

A primeira mudança feita, para essa tarefa, foi criar uma classe genérica para realizar consultas no banco de dados, a Repository/GenericDbContext, e uma classe base para todos os data model, a Models/Entity.cs. Com essas classes foi possível aproveitar o mesmo código para se conectar com diferentes tabelas do banco de dados.

marcelohnq commented 7 months ago

Paginação

Foi construído uma consulta no BD que realiza a paginação, de forma genérica para qualquer entidade:

        public async Task<EntityList<TEntity>> GetPagination(int page, int size = 10)
        {
            int total = _dbSet.AsQueryable().Count();
            int current = (page - 1) * size;
            int last = page * size;

            List<TEntity> list = await _dbSet
                .OrderBy(e => e.Id)
                .Where(e => e.Id > current)
                .Take(size)
                .ToListAsync();

            return new(list) { HasNext = last < total, TotalCount = total };
        }

Aqui existe uma grande preocupação na performance, principalmente quando existir milhões da dados no BD. Para melhorar a performance foi utilizado o Where(e => e.Id > current) em cima da Primary Key das tabelas (essa consulta é executada direto no BD).

Outras possíveis melhorias de performance seria:

marcelohnq commented 7 months ago

Injeção de Dependência

Com a criação da classe genérica, a classe ProductService foi removida. No controlador foi adicionado a injeção de dependência:

// Program.cs
builder.Services.AddScoped(typeof(IGenericDbContext<>), typeof(GenericDbContext<>));

E alterado no controlador:

// Parte2Controller
private readonly IGenericDbContext<Product> _ctxProducts;
private readonly IGenericDbContext<Customer> _ctxCustomer;
marcelohnq commented 7 months ago

Repetição de código

As classes Models/CustomerList e Models/ProductList foram trocadas pela classe Models/EntityList.cs.

A criação do GenericDbContext resolveu a repetição de código nas classes CustomerService e ProductService, que apenas realizava consultas no BD.