Utilitário de linha de comando em .NET que copia todas as tabelas de um banco SQL Server para PostgreSQL, com suporte a retomada automática, validação final e geração de relatório HTML.
- .NET 9 SDK instalado
- Acesso aos servidores SQL Server (origem) e PostgreSQL (destino)
- Firewall/liberação para que a máquina onde o utilitário roda alcance os dois servidores
- Atualize o arquivo
appsettings.jsoncom as strings de conexão:{ "SqlServer": { "ConnectionString": "Server=SQL_SERVER;Database=DB_A;User Id=sa;Password=Senha;TrustServerCertificate=True;" }, "Postgres": { "ConnectionString": "Host=POSTGRES_HOST;Database=DB_B;Username=postgres;Password=Senha;Include Error Detail=true;" }, "Runtime": { "BatchSize": 1000, "StateFile": "migration_state.json", "ReportFile": "Reports/migration_report.html", "ExpectedTableCount": 33, "Debug": false, "DebugRowLimit": 500, "Tables": [], "ExcludedTables": [] }
}
- `BatchSize`: número de linhas lidas por lote no SQL Server.
- `StateFile`: caminho onde o progresso da migração é salvo (usar caminho absoluto ou relativo ao appsettings).
- `ReportFile`: destino do relatório HTML final (pastas inexistentes são criadas automaticamente).
- `ExpectedTableCount`: número esperado de tabelas na origem; se a consulta retornar uma quantidade diferente o processo é interrompido.
- `Debug`: quando `true`, limita a cópia a `DebugRowLimit` registros por tabela para testes rápidos.
- `DebugRowLimit`: quantidade máxima de registros copiados por tabela no modo debug (padrão 500).
- `Tables`: lista opcional de tabelas (schema.nome) a serem migradas. Vazio = todas.
- `ExcludedTables`: lista opcional de tabelas para ignorar.
## Execução
```bash
# dentro da pasta do projeto
dotnet run -- appsettings.json
- Se o arquivo não for informado,
appsettings.jsonna pasta atual é usado por padrão. - Pressione
CTRL+Cpara cancelar com segurança; o estado é salvo e a próxima execução retoma de onde parou.
- Lê o schema do SQL Server e garante que esquemas/tabelas existam no PostgreSQL (criando colunas que não existirem).
- Copia os dados por lotes, respeitando chave primária quando existir e exibindo barra de progresso + ETA em tempo real.
- Tabelas sem relacionamentos (ou com 0 linhas) são migradas em paralelo para ganhar tempo, enquanto as dependentes rodam em sequência.
- Persiste o avanço em
migration_state.jsona cada lote para permitir retomada sem duplicar registros. - Ao final, reconta as linhas em todas as tabelas de origem/destino e indica divergências.
- Gera um relatório HTML com resumo, tempos, quantidades, erros e mensagens por tabela.
migration_state.json: estado persistido da migração.migration_report.html: relatório completo com sucesso/falha de cada tabela.- Console: logs resumidos + barra de progresso/ETA.
- Para tabelas sem chave primária, a ordenação usa todas as colunas, o que pode impactar performance.
- Tipos de dados não mapeados explicitamente são convertidos para
TEXTno PostgreSQL. - O comando
INSERTusaON CONFLICT DO NOTHING, evitando erro em execuções repetidas.