Pular para o conteúdo principal

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 using necessá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:

  1. Código mais limpo e legível
  2. Reutilização de mapeamentos
  3. Facilidade de manutenção
  4. Consistência no projeto
  5. Menos propensão a erros

Substitua sempre o mapeamento manual por mappings configurados para melhorar a qualidade e manutenibilidade do código.