Documentação: Como usar Mappings para substituir código manual
Visão Geral
Este tutorial explica como usar o sistema de mappings customizado do projeto para substituir o mapeamento manual com Select LINQ, baseado no exemplo das condições de pagamento.
Problema Atual
O código atual usa mapeamento manual com Select:
// ❌ Abordagem manual (atual)
var response = new CondicaoPagamentoResponseDto();
response.Items = entityCondicaoPagamentoService
.Select(a => new CondicaoPagamentoItemDto
{
Id = a.Id,
Descricao = a.Descricao
})
.ToList();
Solução com Mappings
Passo 1: Criar a Entidade (se não existir)
// CondicaoPagamentoEntity.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace SGApi.CondicoesPagamentos
{
[Table("condicao_pagamento")] // Ajuste para o nome real da tabela
public class CondicaoPagamentoEntity
{
[Key]
[Column("id")]
public int Id { get; set; }
[Column("descricao")]
public string Descricao { get; set; }
[Column("ativo")]
public string Ativo { get; set; }
[Column("tipo")]
public int Tipo { get; set; }
}
}
Passo 2: Criar a classe de Mapping
// CondicaoPagamentoMappings.cs
namespace SGApi.CondicoesPagamentos
{
public static class CondicaoPagamentoMappings
{
public static void Configure()
{
CompactMapperExtension.AddCustomMapping<CondicaoPagamentoEntity, CondicaoPagamentoItemDto>((source, destination) =>
{
destination.Id = source.Id;
destination.Descricao = source.Descricao;
});
}
}
}
Passo 3: Registrar no Program.cs
// Program.cs - Adicionar após UltimoMappings.Configure();
using SGApi.CondicoesPagamentos;
// ... código existente ...
ClienteMappings.Configure();
CondicaoPagamentoMappings.Configure(); // ✅ Adicionar essa linha
// ... resto do código ...
Passo 4: Atualizar o Controller
// CondicoesPagamentosController.cs
public ActionResult<CondicoesPagamentosResponseDto> SincronizacaoCondicoesPagamentos([FromBody] PaginacaoDto paginacao)
{
var entityCondicaoPagamento = _context.CondicaoPagamento
.Where(x => x.Ativo == "1" && x.Tipo != 9)
.ToList();
if (entityCondicaoPagamento.Count > 0)
{
var response = new CondicoesPagamentosResponseDto();
// ✅ Usando MapTo ao invés do Select manual
response.Items = entityCondicaoPagamento
.Select(entity => entity.MapTo<CondicaoPagamentoItemDto>())
.ToList();
return Ok(response);
}
throw new NotImplementedException("Lógica de sincronização não implementada");
}
Vantagens da Abordagem com Mappings
1. Menos Código
// ❌ Antes (manual)
response.Items = entityCondicaoPagamento
.Select(a => new CondicaoPagamentoItemDto
{
Id = a.Id,
Descricao = a.Descricao
})
.ToList();
// ✅ Depois (com mapping)
response.Items = entityCondicaoPagamento
.Select(entity => entity.MapTo<CondicaoPagamentoItemDto>())
.ToList();
2. Reutilização
O mesmo mapeamento pode ser usado em outros lugares:
// Em outro método
var dto = entity.MapTo<CondicaoPagamentoItemDto>();
// Em outro controller
var dtos = entities.Select(e => e.MapTo<CondicaoPagamentoItemDto>()).ToList();
3. Manutenibilidade
Se as propriedades mudarem, você só precisa atualizar o mapping:
// Se a propriedade mudar de "Descricao" para "Nome"
CompactMapperExtension.AddCustomMapping<CondicaoPagamentoEntity, CondicaoPagamentoItemDto>((source, destination) =>
{
destination.Id = source.Id;
destination.Descricao = source.Nome; // ✅ Apenas uma linha para mudar
});
Exemplos Avançados de Mapping
1. Mapeamento com Transformação
CompactMapperExtension.AddCustomMapping<CondicaoPagamentoEntity, CondicaoPagamentoItemDto>((source, destination) =>
{
destination.Id = source.Id;
destination.Descricao = source.Descricao?.Trim().ToUpper();
destination.Ativo = source.Ativo == "1";
});
2. Mapeamento com Lógica Condicional
CompactMapperExtension.AddCustomMapping<CondicaoPagamentoEntity, CondicaoPagamentoItemDto>((source, destination) =>
{
destination.Id = source.Id;
destination.Descricao = !string.IsNullOrEmpty(source.Descricao)
? source.Descricao.Trim()
: "Sem descrição";
});
3. Mapeamento com Validação
CompactMapperExtension.AddCustomMapping<CondicaoPagamentoEntity, CondicaoPagamentoItemDto>((source, destination) =>
{
destination.Id = source.Id;
destination.Descricao = source.Descricao ?? "Descrição não informada";
// Validação adicional Usar apenas quando for extremamente necessário
if (source.Tipo == 9)
{
destination.Descricao = $"{destination.Descricao} (Especial)";
}
});
Estrutura de Arquivos Recomendada
CondicoesPagamentos/
├── CondicaoPagamentoEntity.cs // Entidade do banco
├── CondicaoPagamentoItemDto.cs // DTO de resposta
├── CondicoesPagamentosResponseDto.cs // DTO de resposta completa
├── CondicoesPagamentosController.cs // Controller
└── CondicaoPagamentoMappings.cs // ✅ Classe de mapeamento
Padrões de Nomenclatura
1. Classe de Mapping
- Nome:
{Entidade}Mappings - Exemplo:
CondicaoPagamentoMappings
2. Método de Configuração
- Sempre chamado
Configure() - Método estático
3. Namespace
- Mesmo namespace da entidade/DTO
- Exemplo:
SGApi.CondicoesPagamentos
Encontrando Problemas
1. Mapping não funciona
- Verifique se o mapping foi registrado no
Program.cs - Confirme se os nomes das propriedades estão corretos
- Verifique se não há erros de compilação
2. Propriedades não mapeadas
- Verifique se a propriedade existe na entidade e no DTO
- Confirme se o tipo de dados é compatível
- Use mapeamento customizado para propriedades com nomes diferentes
3. Erro de compilação
- Verifique se todos os
usingnecessários estão presentes - Confirme se a classe de mapping é estática
- Verifique se o método
Configure()é estático
Conclusão
Usar o sistema de mappings customizado oferece várias vantagens:
- Código mais limpo e legível
- Reutilização de mapeamentos
- Facilidade de manutenção
- Consistência no projeto
- Menos propensão a erros
Substitua sempre o mapeamento manual por mappings configurados para melhorar a qualidade e manutenibilidade do código.