Remoção do Relacionamento TipoFamilia da Entidade Liga
Versão: 1.0 Data: 2025-10-27 Status: ✅ Implementado Tarefa: NH-85
Visão Geral
Este documento registra a decisão arquitetural de remover o relacionamento entre as entidades Liga e TipoFamilia, eliminando a foreign key TipoFamiliaId da tabela Liga. Esta mudança simplifica o modelo de domínio e resolve problemas de duplicação de códigos de liga.
Contexto
Problema Identificado
No módulo de Cadastro de Mercadorias (Liga/Norma/Composição/Propriedade/Aplicação), identificou-se que o campo TipoFamiliaId na entidade Liga estava causando problemas:
- Duplicação de Códigos: O mesmo código de liga podia ser cadastrado múltiplas vezes com diferentes tipos de família, causando inconsistências
- Complexidade Desnecessária: O relacionamento com
TipoFamilianão era utilizado em outras partes do sistema - Acoplamento Excessivo: A dependência entre
LigaeTipoFamilianão trazia benefícios ao modelo de negócio
Telas Afetadas
/cadastros/lista-liga- Listagem de ligas (incluía coluna "Tipo de Família")/cadastros/adicionar-liga- Formulário de adição (incluía campo "Tipo de Família")/cadastros/atualizar-liga/{id}- Formulário de edição (incluía campo "Tipo de Família")
Análise de Impacto
Foi realizada análise completa do codebase e confirmado que:
- ✅ O campo TipoFamiliaId não era usado em regras de negócio
- ✅ Não havia dependências em outros módulos
- ✅ A remoção simplificaria o modelo sem perda de funcionalidade
- ✅ O código da liga por si só é suficiente para identificação única
Decisão
Remover completamente o relacionamento entre Liga e TipoFamilia, incluindo:
- Foreign key
TipoFamiliaIdda tabelaLiga - Propriedade de navegação
TipoFamiliado modeloLiga - Coleção de navegação
Ligasdo modeloTipoFamilia - Validações relacionadas a
TipoFamiliaIdemLigaValidation - Configurações EF Core em
LigaConfiguration - Includes desnecessários em
LigaRepository - Campo
TipoFamiliaIdde ViewModels e Controllers - Exibição de "Tipo de Família" nas views (Index, Create, Edit, Details)
Implementação
1. Alterações no Modelo de Domínio
Arquivo: src/Nelmetais.SGE.Business/Models/Cadastros/Liga.cs
// REMOVIDO:
public int TipoFamiliaId { get; set; }
public virtual TipoFamilia? TipoFamilia { get; set; }
Arquivo: src/Nelmetais.SGE.Business/Models/Cadastros/TipoFamilia.cs
2. Validações
Arquivo: src/Nelmetais.SGE.Business/Validations/Cadastros/LigaValidation.cs
Removidas validações do campo TipoFamiliaId:
- Verificação de obrigatoriedade
- Validação de valor maior que zero
3. Configuração EF Core
Arquivo: src/Nelmetais.SGE.Data/Configurations/Cadastros/LigaConfiguration.cs
Removida configuração de relacionamento:
// REMOVIDO:
builder.HasOne(l => l.TipoFamilia)
.WithMany(tf => tf.Ligas)
.HasForeignKey(l => l.TipoFamiliaId);
4. Repository
Arquivo: src/Nelmetais.SGE.Data/Repositories/Cadastros/LigaRepository.cs
Removidos includes desnecessários:
5. Controllers e ViewModels
Arquivo: src/Nelmetais.SGE.WebApp/Areas/Cadastros/Controllers/LigaController.cs
Removidas:
- Propriedade TipoFamiliaId do ViewModel
- População de ViewBag.TipoFamilias
- Validação do campo no método Create/Edit
Arquivo: src/Nelmetais.SGE.WebApp/Areas/Cadastros/ViewModels/LigaViewModel.cs
// REMOVIDO:
[Display(Name = "Tipo de Família")]
[Required(ErrorMessage = "O campo {0} é obrigatório")]
public int TipoFamiliaId { get; set; }
[Display(Name = "Tipo de Família")]
public string? TipoFamiliaNome { get; set; }
6. Views
Removido campo "Tipo de Família" de todas as views:
- Index.cshtml - Coluna na tabela de listagem
- _LigaCreateEditPartial.cshtml - Campo select no formulário
- _Details.cshtml - Campo de exibição nos detalhes
7. Migration de Banco de Dados
Arquivo: src/Nelmetais.SGE.Data/Migrations/20251027185653_RemoverTipoFamiliaIdDeLiga.cs
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Liga_TipoFamilia_TipoFamiliaId",
table: "Liga");
migrationBuilder.DropIndex(
name: "IX_Liga_TipoFamiliaId",
table: "Liga");
migrationBuilder.DropColumn(
name: "TipoFamiliaId",
table: "Liga");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "TipoFamiliaId",
table: "Liga",
type: "integer",
nullable: false,
defaultValue: 0);
migrationBuilder.CreateIndex(
name: "IX_Liga_TipoFamiliaId",
table: "Liga",
column: "TipoFamiliaId");
migrationBuilder.AddForeignKey(
name: "FK_Liga_TipoFamilia_TipoFamiliaId",
table: "Liga",
column: "TipoFamiliaId",
principalTable: "TipoFamilia",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
8. Ajustes de UI
Arquivo: src/Nelmetais.SGE.WebApp/Areas/Cadastros/Views/Liga/Index.cshtml
Ajustadas as larguras das colunas para melhor aproveitamento do espaço após remoção da coluna "Tipo de Família": - Coluna "Código": 10% → 12% - Coluna "Nome": 15% → 18% - Coluna "Aplicação": 15% → 18%
Commits Relacionados
- 224d7b3c -
refactor: Remove TipoFamiliaId relationship from Liga entity - Remove propriedades e navegações
- Remove validações e configurações
-
Remove campos de controllers, viewmodels e views
-
67720184 -
build: Add database migration to remove TipoFamiliaId from Liga -
Migration para remover FK e coluna do banco de dados
-
9f28a8d7 -
fix: Correct view directory names for Linux case sensitivity -
Correção de case sensitivity em nomes de views
-
596e4ad6 -
style: Adjust column widths in Liga listing table - Ajuste de larguras das colunas após remoção
Consequências
Positivas ✅
- Modelo Simplificado: Entidade
Ligamais enxuta e focada em sua responsabilidade - Sem Duplicação: Impossível ter múltiplas ligas com mesmo código (mas tipos de família diferentes)
- Menos Acoplamento:
Liganão depende mais deTipoFamilia - Performance: Menos joins no banco de dados ao carregar ligas
- Manutenibilidade: Menos código para manter em validações, configurações e views
- Código Único: O código da liga agora é verdadeiramente único no sistema
Negativas ⚠️
- Perda de Informação: Não é mais possível categorizar ligas por tipo de família
-
Mitigação: Esta informação não era utilizada em regras de negócio
-
Reversão Requer Migration: Se necessário reverter, será necessário:
- Executar migration Down
- Repopular dados de
TipoFamiliaIdmanualmente - Restaurar código removido
Alternativas Consideradas
Alternativa 1: Manter Campo Como Opcional
- Prós: Menor impacto de mudança
- Contras: Campo inútil permaneceria no modelo, aumentando complexidade
Alternativa 2: Adicionar Constraint Único Composto (Código + TipoFamiliaId)
- Prós: Permitiria duplicação controlada
- Contras: Não resolve o problema de fundo (campo desnecessário)
Alternativa 3: Remover Apenas da UI
- Prós: Dados preservados no banco
- Contras: Campo fantasma no modelo, confusão para desenvolvedores
Procedimento de Deploy
Ambientes de Desenvolvimento/Homologação
# Aplicar migration automaticamente
dotnet ef database update --project src/Nelmetais.SGE.Data \
--startup-project src/Nelmetais.SGE.WebApp
Ambiente de Produção (UAT)
- Backup do banco de dados
- Gerar script SQL da migration:
- Validar script manualmente
- Executar script no banco UAT:
- Verificar se a coluna foi removida:
Impacto em Dados Existentes
⚠️ ATENÇÃO: Esta migration remove dados da coluna TipoFamiliaId.
Dados Perdidos
- Relacionamentos entre ligas existentes e seus tipos de família
- Não há dados dependentes (nenhuma outra tabela referencia esta FK)
Recuperação
Se necessário recuperar os dados após a migration:
1. Restaurar backup do banco de dados
2. Exportar dados de TipoFamiliaId antes de aplicar migration
3. Reverter migration: dotnet ef database update <previous-migration>
4. Reimportar dados se necessário
Monitoramento Pós-Deploy
Checklist de Validação
- [ ] Migration aplicada com sucesso no banco de dados
- [ ] Coluna
TipoFamiliaIdremovida da tabelaLiga - [ ] Foreign key
FK_Liga_TipoFamilia_TipoFamiliaIdremovida - [ ] Tela de listagem (
/cadastros/lista-liga) funcionando sem erros - [ ] Formulário de adição (
/cadastros/adicionar-liga) funcionando sem campo Tipo Família - [ ] Formulário de edição (
/cadastros/atualizar-liga/{id}) funcionando sem campo Tipo Família - [ ] Tela de detalhes não exibe Tipo de Família
- [ ] Validações de código único funcionando corretamente
- [ ] Não há erros de missing includes no log da aplicação
Testes Funcionais
- Criar Nova Liga
- Acessar
/cadastros/adicionar-liga - Preencher código, nome e outros campos
- Verificar que não aparece campo "Tipo de Família"
-
Salvar e confirmar sucesso
-
Editar Liga Existente
- Acessar
/cadastros/lista-liga - Clicar em editar qualquer liga
- Verificar que não aparece campo "Tipo de Família"
- Editar outros campos
-
Salvar e confirmar sucesso
-
Visualizar Detalhes
- Na listagem, clicar em detalhes de uma liga
-
Confirmar que "Tipo de Família" não é exibido
-
Validação de Código Único
- Tentar criar liga com código já existente
- Confirmar que validação de unicidade funciona
Referências
- Tarefa: NH-85
- Branch:
fix/remove-tipo-familia-from-liga-NH-85 - Pull Request: [Pendente]
- Migration:
20251027185653_RemoverTipoFamiliaIdDeLiga - Documentação de Migrations:
docs/CORRECAO-MIGRATIONS.md - Documentação de UAT:
docs/ATUALIZACAO-BANCO-UAT.md
Histórico de Revisões
| Versão | Data | Autor | Descrição |
|---|---|---|---|
| 1.0 | 2025-10-27 | Bruno Martins | Documentação inicial da mudança |
Aprovações
- [x] Desenvolvedor: Bruno Martins
- [ ] Revisor Técnico: _
- [ ] Product Owner: _
- [ ] DBA/Infra: _