Camada de Infra - Data
O projeto WMS.AI.Infra.Data é responsável pela persistência de dados do WMS.
Ele abstrai o acesso ao banco de dados e fornece repositórios modulares para diferentes contextos do sistema.
A implementação é baseada principalmente no Entity Framework Core, mas há suporte para consultas específicas via Dapper/SQL quando necessário.
Estrutura de Pastas
- Extensions → Métodos de extensão usados para registrar os
DbContextse repositórios no container de DI. - Helpers → Utilitários auxiliares relacionados a persistência e banco de dados.
- Persistence → Contém toda a lógica de persistência.
- Contexts → múltiplos
DbContextdivididos por escopo (ex: pedidos, produtos, endereços). - Repositories → implementações modulares de repositórios para cada domínio.
- RepositoryBase.cs → implementação base de repositório genérico em EF, permitindo reutilização.
- Contexts → múltiplos
- Tenants → Estruturas relacionadas a multi-tenancy, permitindo isolar dados por cliente/instância.
Contexts
Cada DbContext representa um escopo específico do domínio e organiza as entidades relacionadas.
Exemplo:
PedidoContext→ lida com tabelas de pedidos.ProdutoContext→ lida com tabelas de produtos.EnderecoContext→ lida com tabelas de endereçamento.
Esse design modular reduz uso de memória, facilita manutenção, isolamento e escalabilidade.
Repositórios
Os repositórios seguem um modelo modular (ex: PedidosRepository, ProdutosRepository), implementam IRepositoryBase e herdam de um repositório base que encapsula operações comuns com Entity Framework.
Exemplo de Repositório com Entity Framework
public interface IEnderecoRepository : IRepositoryBase<Endereco>{}
public class EnderecoRepository(EnderecoContext context)
: RepositoryBase<Endereco, EnderecoContext>(context), IEnderecoRepository
{
// Operações mais especificas e/ou atômicas podem ser adicionadas aqui.
}
Ao herdar do RepositoryBase, temos acesso à todas as operações comuns de um repositório:
public interface IRepositoryBase<TEntity> where TEntity : class
{
IQueryable<TEntity> GetAll();
IQueryable<TEntity> GetById(object id);
Task<bool> ExistsAsync(object id, CancellationToken cancellationToken = default);
Task<bool> ExistsAsync(
Expression<Func<TEntity, bool>> predicate,
CancellationToken cancellationToken = default);
Task<List<TEntity>> GetAllAsync(CancellationToken cancellationToken = default);
Task<TEntity?> GetByIdAsync(object id, CancellationToken cancellationToken = default);
Task<List<TEntity>> FindAsync(Expression<Func<TEntity, bool>> predicate,
CancellationToken cancellationToken = default);
Task AddAsync(TEntity entity, CancellationToken cancellationToken = default);
Task AddRangeAsync(
IEnumerable<TEntity> entities,
CancellationToken cancellationToken = default);
Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default);
Task RemoveAsync(TEntity entity, CancellationToken cancellationToken = default);
Task RemoveByIdAsync(object id, CancellationToken cancellationToken = default);
Task<int> ExecuteUpdateAsync(
Expression<Func<TEntity, bool>> predicate,
Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> setProperties,
CancellationToken cancellationToken = default
);
Task<int> ExecuteDeleteAsync(
Expression<Func<TEntity, bool>> predicate,
CancellationToken cancellationToken = default
);
}