Pular para conteúdo

Correção: Migrations do Banco de Dados Não Funcionando

Problema

As migrations do Entity Framework estavam falhando ao executar localmente com o seguinte erro:

System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString')

Causa Raiz

A aplicação estava configurada para receber a connection string via variável de ambiente ConnectionStrings:DefaultConnection (usada no Docker), mas esta variável não estava disponível ao executar comandos dotnet ef localmente.

A connection string estava sendo definida apenas no arquivo docker-compose.yml:

environment:
  - "ConnectionStrings:DefaultConnection=Server=${SGE_DB_HOST:-database};Port=${SGE_DB_PORT:-5432};..."

Solução

Modificado WebAppConfiguration.cs para construir a connection string a partir de variáveis de ambiente individuais quando a connection string completa não for fornecida. Isso permite que a aplicação funcione tanto com Docker (usando ConnectionStrings:DefaultConnection) quanto localmente (usando variáveis SGE_DB_* individuais do arquivo .env).

Alterações em src/Nelmetais.SGE.WebApp/Configurations/WebAppConfiguration.cs:

// Tenta obter a connection string da configuração primeiro (variável de ambiente ou appsettings)
var connectionString = configuration["ConnectionStrings:DefaultConnection"];

// Se não encontrar, constrói a partir de variáveis de ambiente individuais (para desenvolvimento local)
if (string.IsNullOrEmpty(connectionString))
{
    var host = Environment.GetEnvironmentVariable("SGE_DB_HOST") ?? "localhost";
    var port = Environment.GetEnvironmentVariable("SGE_DB_PORT") ?? "5432";
    var database = Environment.GetEnvironmentVariable("SGE_DB_SCHEMA") ?? "NelmetaisDB";
    var user = Environment.GetEnvironmentVariable("SGE_DB_USER") ?? "postgres";
    var password = Environment.GetEnvironmentVariable("SGE_DB_PASSWORD") ?? "";

    connectionString = $"Server={host};Port={port};Database={database};User Id={user};Password={password}";
}

Abordagem de Teste

  1. Criado um banco de dados de teste separado (NelmetaisDB_test) para evitar afetar o banco de produção
  2. Modificado arquivo .env para usar banco de teste: SGE_DB_SCHEMA=NelmetaisDB_test
  3. Verificado que todas as migrations podem ser aplicadas com sucesso usando variáveis de ambiente

Como Executar Migrations Localmente

Pré-requisitos

  • Ferramenta dotnet-ef instalada (versão 6.0.18 para compatibilidade com .NET 6)
  • Servidor de banco de dados acessível no host/porta configurados
  • Credenciais do banco configuradas no arquivo .env na raiz do projeto

Configuração de Variáveis de Ambiente

Certifique-se de que seu arquivo .env contém:

SGE_DB_HOST=192.168.3.140
SGE_DB_PORT=54432
SGE_DB_SCHEMA=NelmetaisDB      # ou NelmetaisDB_test para testes
SGE_DB_USER=postgres
SGE_DB_PASSWORD=sua_senha
SGE_ENVIRONMENT=Development

Comandos

Usando Make (Recomendado - MAIS FÁCIL!)

O Makefile foi atualizado para carregar automaticamente as variáveis do .env. Simplesmente use:

make migration-list                  # Listar todas as migrations e seus status
make migrate                         # Aplicar migrations pendentes
make migration NAME=MinhaFeature     # Criar nova migration
make migration-script                # Gerar script SQL das migrations

Todos os comandos leem automaticamente do arquivo .env - não é necessário exportar variáveis manualmente!

Comandos Manuais (se necessário)

IMPORTANTE: Todos os comandos dotnet ef devem ser executados com variáveis de ambiente carregadas do .env:

Listar migrations:

bash -c 'source .env && export SGE_DB_HOST SGE_DB_PORT SGE_DB_SCHEMA SGE_DB_USER SGE_DB_PASSWORD && \
~/.dotnet/tools/dotnet-ef migrations list \
  --project src/Nelmetais.SGE.Data \
  --startup-project src/Nelmetais.SGE.WebApp'

Aplicar migrations:

bash -c 'source .env && export SGE_DB_HOST SGE_DB_PORT SGE_DB_SCHEMA SGE_DB_USER SGE_DB_PASSWORD && \
~/.dotnet/tools/dotnet-ef database update \
  --project src/Nelmetais.SGE.Data \
  --startup-project src/Nelmetais.SGE.WebApp'

Criar nova migration:

bash -c 'source .env && export SGE_DB_HOST SGE_DB_PORT SGE_DB_SCHEMA SGE_DB_USER SGE_DB_PASSWORD && \
~/.dotnet/tools/dotnet-ef migrations add <NomeDaMigration> \
  --project src/Nelmetais.SGE.Data \
  --startup-project src/Nelmetais.SGE.WebApp'

Migrations Aplicadas

As seguintes migrations foram aplicadas com sucesso no banco de dados de teste:

  1. 20250111135936_initialcreate
  2. 20250111143052_documento-fiscal-comissao
  3. 20250111164642_documento-fiscal-comissao-planocomissaovenda
  4. 20250121125526_NM2-Documento-Fiscal-Terceiros1
  5. 20250121222434_NM2-Documento-Fiscal-Terceiros2
  6. 20250123204156_NM-vendedor-delegado

Todas as migrations foram aplicadas com sucesso usando Entity Framework Core versão 6.0.18.

Observações Importantes

  1. Segurança: Todas as credenciais são armazenadas no arquivo .env que já está no .gitignore. Nunca faça commit de credenciais no controle de versão.

  2. Separação de Ambientes: Use SGE_DB_SCHEMA=NelmetaisDB_test no .env para testar migrations de forma segura, separado do banco de produção.

  3. Docker vs Local:

  4. Docker: Usa a variável de ambiente ConnectionStrings:DefaultConnection construída a partir das variáveis SGE_DB_* individuais
  5. Desenvolvimento local: Lê as variáveis de ambiente SGE_DB_* individuais e constrói a connection string no código

  6. Problemas de Build: Se encontrar erros "Text file busy" durante o build, significa que a aplicação está em execução. Mate o processo primeiro:

    lsof +D src/Nelmetais.SGE.WebApp/bin | grep Nelmetais | awk '{print $2}' | xargs kill -9
    dotnet clean src/Nelmetais.SGE.WebApp/Nelmetais.SGE.WebApp.csproj
    

  7. Retrocompatibilidade: A solução mantém total retrocompatibilidade com deployments Docker. Nenhuma alteração em docker-compose.yml ou scripts de deploy é necessária.

Arquivos Modificados

  • src/Nelmetais.SGE.WebApp/Configurations/WebAppConfiguration.cs - Adicionada lógica de fallback para construir connection string a partir de variáveis de ambiente individuais
  • Makefile - Comandos de migration atualizados para usar variáveis de ambiente individuais em vez de connection string completa

Testes Realizados

  • Criado banco de dados de teste NelmetaisDB_test
  • Listadas todas as migrations pendentes (6 no total)
  • Aplicadas todas as migrations com sucesso
  • Verificadas migrations na tabela __EFMigrationsHistory