Migrations com EF Core, .NET 5 e PostgreSQL
Criar migrations no PostgreSQL com o Entity Framework Core é a saída ideal para quem não pode, ou não quer, usar MySQL em uma API REST no .NET 5. Neste guia, você vai configurar o projeto, conectar ao banco e gerar as tabelas a partir do seu modelo, tanto no Windows quanto no macOS.
Por que usar migrations no PostgreSQL
Este guia nasceu de uma situação bastante comum para quem está começando. Em um macOS Catalina 10.15.7, a versão do MySQL disponível exigia o macOS 11 ou superior, e trocar de computador não era uma opção naquele momento.
A alternativa foi buscar em fóruns e sites como criar migrations no PostgreSQL com o .NET 5. Como a resposta não estava reunida em um único lugar, este artigo consolida toda a pesquisa feita para resolver o problema.
O PostgreSQL é um banco de dados relacional open source, maduro e com excelente suporte no ecossistema .NET. Além disso, ele roda bem no Windows, no Linux e no macOS, o que o torna uma escolha natural para máquinas com restrições.
A importância do aprendizado contínuo
Apenas duas semanas depois de escrever a primeira versão deste conteúdo, surgiu outra descoberta em um curso do balta.io. Seria possível usar o Docker com SQL Server, sem instalar o banco diretamente na máquina.
Se você preferir esse caminho, o artigo sobre SQL Server no Docker mostra o passo a passo. Ainda assim, o PostgreSQL continua sendo uma ótima escolha, e as etapas a seguir valem para qualquer projeto que precise dele.
O que você precisa instalar
Primeiro, você precisa de três itens na sua máquina: o SDK do .NET 5, o Postman para testar a API e o próprio PostgreSQL. Caso ainda não tenha o .NET, veja o guia de instalação e primeiros passos com .NET.
Aqui vai uma dica importante sobre o PostgreSQL. Prefira baixar o instalador oficial, porque pelo Homebrew, o gerenciador de pacotes do macOS, você terá que configurar usuário e senha por linha de comando após a instalação.
Se você é iniciante nessas ferramentas, essa configuração manual pode dar bastante trabalho. Por outro lado, o instalador já pede a senha do usuário administrador e instala o pgAdmin 4, a interface gráfica do banco.
Também é possível rodar o PostgreSQL em um contêiner. Nesse caso, o artigo sobre Docker: instalação, configuração e primeiros passos ajuda a preparar o ambiente.
Pacotes NuGet para migrations no PostgreSQL
Com o projeto aberto no .NET 5, adicione os seguintes pacotes pelo NuGet. Para manter a compatibilidade, use as versões 5.x de cada um deles.
- Microsoft.EntityFrameworkCore
- Npgsql.EntityFrameworkCore.PostgreSQL
- Microsoft.EntityFrameworkCore.Design
- NuGet.CommandLine
- Microsoft.EntityFrameworkCore.Tools
No geral, esses pacotes fornecem o acesso a dados com objetos .NET, a conexão com o PostgreSQL e o trabalho com o NuGet pela linha de comando. Em seguida, vale entender o papel de cada um.
O papel de cada pacote
O Microsoft.EntityFrameworkCore é o núcleo do ORM, enquanto o Npgsql.EntityFrameworkCore.PostgreSQL é o provider que traduz as operações para o PostgreSQL. Sem o provider, o EF Core não sabe conversar com esse banco.
Já o Microsoft.EntityFrameworkCore.Design é obrigatório para as ferramentas de design, como as migrations no PostgreSQL. O Microsoft.EntityFrameworkCore.Tools, por sua vez, habilita os comandos do Package Manager Console no Visual Studio.
O NuGet.CommandLine permite usar o NuGet pelo terminal, mas não é obrigatório para as migrations. Portanto, se você só vai usar o dotnet ef, ele pode ficar de fora.
Pela linha de comando, a instalação fica assim. Lembre-se de executar dentro da pasta onde está o arquivo .csproj.
# adiciona os pacotes do EF Core e do provider do PostgreSQL (versões 5.x)
dotnet add package Microsoft.EntityFrameworkCore --version 5.0.*
dotnet add package Microsoft.EntityFrameworkCore.Design --version 5.0.*
dotnet add package Microsoft.EntityFrameworkCore.Tools --version 5.0.*
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 5.0.*
Uma observação para quem usa macOS
Se você usa o .NET em um macOS, não terá o Package Manager Console funcional no Visual Studio. Segundo a documentação de instalação do EF Core, as ferramentas do PMC rodam no Visual Studio para Windows.
Nesse caso, a solução é usar o terminal do sistema operacional com as ferramentas de linha de comando do .NET. Mais adiante, veremos exatamente quais comandos executar.
Conectando ao banco de dados PostgreSQL
Antes de gerar migrations no PostgreSQL, o projeto precisa de um modelo e de um contexto. Para ilustrar, vamos usar uma entidade Video e o contexto VideoContext.
// Models/Video.cs
public class Video
{
public int Id { get; set; }
public string Title { get; set; }
public string Url { get; set; }
}
// Data/VideoContext.cs
public class VideoContext : DbContext
{
public VideoContext(DbContextOptions<VideoContext> options)
: base(options) { }
public DbSet<Video> Videos { get; set; }
}
Cada DbSet vira uma tabela quando aplicamos as migrations no PostgreSQL. Assim, a classe Video gera a tabela Videos, com uma coluna para cada propriedade.
Criando a string de conexão
Com usuário e senha do banco em mãos, crie a string de conexão no arquivo appsettings.json do projeto, conforme o modelo abaixo.
{
"DbContextSettings": {
"ConnectionString": "User ID=your_username;Password=your_password;Host=localhost;Port=5432;Database=your_database;Pooling=true;"
}
}
Atenção ao trecho User ID=, que leva um espaço entre as palavras User e ID. Além disso, o nome de usuário, a senha e o nome do banco não podem conter espaços.
Para criar migrations no PostgreSQL, você não precisa criar o banco manualmente pelo pgAdmin 4. Basta informar o nome desejado nessa configuração, e o comando de atualização das migrations cria o banco e as tabelas automaticamente.
O provider Npgsql também aceita o formato Host=...;Database=...;Username=...;Password=..., usado na documentação oficial. Portanto, escolha o que preferir, desde que os valores estejam corretos.
Registrando o contexto no Startup
Em seguida, dentro do método ConfigureServices do arquivo Startup.cs, leia a string de conexão e registre o contexto. Dessa forma, a configuração roda sempre na inicialização da aplicação.
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration["DbContextSettings:ConnectionString"];
services.AddDbContext<VideoContext>(options =>
options.UseNpgsql(connectionString));
services.AddControllers();
}
O método UseNpgsql vem do provider e indica ao EF Core que as migrations no PostgreSQL são o destino do modelo. Se o editor não reconhecer os tipos, use Alt + Enter para adicionar os using necessários, como Microsoft.EntityFrameworkCore.
macOS: um passo antes das migrations no PostgreSQL
Se o seu Visual Studio está instalado no Windows, você pode seguir direto para a próxima seção. Afinal, o Package Manager Console já atende o fluxo completo.
Caso esteja no macOS, execute os comandos abaixo no terminal antes de criar as migrations no PostgreSQL. Pode ser o terminal integrado ao editor ou o do próprio sistema.
# instala as ferramentas do EF Core como ferramenta global
dotnet tool install --global dotnet-ef
# verifica se a instalação funcionou
dotnet ef
A instalação dessa ferramenta de linha de comando é necessária para executar as migrations pelo terminal. Desde o EF Core 3.0, o dotnet ef não vem mais junto com o SDK e precisa ser instalado à parte.
Se o comando dotnet ef exibir o logo do Entity Framework e a versão das ferramentas, está tudo certo. Caso contrário, verifique se a pasta de ferramentas globais do .NET está no PATH do terminal.
Para se aprofundar, consulte a visão geral da CLI do .NET e a referência das ferramentas do EF Core para a CLI.
Gerando migrations no PostgreSQL com .NET 5
Finalmente chegamos à etapa principal deste artigo. Para começar, sua API REST precisa estar criada, ou seja, com models, controllers, conexão configurada e projeto compilando sem erros.
No Windows, abra o Package Manager Console do Visual Studio e execute os comandos na ordem indicada. No macOS, certifique-se de que o terminal está dentro da pasta do projeto, onde fica o arquivo .csproj.
Criando a primeira migration
O primeiro comando cria a migration inicial a partir do modelo da sua API. Pela CLI, use o comando abaixo.
# cria a migration inicial com base no modelo
dotnet ef migrations add InitialCreate
No Package Manager Console, o equivalente é Add-Migration InitialCreate. Em ambos os casos, o EF Core cria a pasta Migrations com os arquivos da migration e um snapshot do modelo.
Esse snapshot registra o estado atual das entidades. Assim, nas próximas migrations no PostgreSQL, o EF Core compara o modelo novo com o snapshot e gera apenas as diferenças.
Criando o banco de dados e as tabelas
Depois de criar a migration, aplique-a ao banco com o comando de atualização. No Package Manager Console, o equivalente é Update-Database.
# cria o banco (se não existir) e aplica as migrations pendentes
dotnet ef database update
Pronto, se tudo estiver configurado conforme as seções anteriores, o banco e as tabelas já existem. Agora, coloque a aplicação para rodar, abra o pgAdmin 4 e o Postman e execute os testes necessários.
No pgAdmin 4, você também encontra a tabela __EFMigrationsHistory. É nela que o EF Core registra quais migrations já foram aplicadas ao banco.
Comandos úteis de manutenção
Além dos comandos principais, alguns outros ajudam na manutenção das migrations. O primeiro remove a última migration criada, desde que ela ainda não tenha sido aplicada.
# remove a última migration ainda não aplicada
dotnet ef migrations remove
Quando algo falha, a opção --verbose, ou -v, exibe mais detalhes sobre o erro. Com isso, fica mais fácil descobrir se o problema está na conexão, no contexto ou no modelo.
# mostra informações detalhadas sobre a falha
dotnet ef migrations remove -v
Também é possível listar as migrations do projeto com dotnet ef migrations list. Esse comando mostra quais existem e, quando consegue acessar o banco, quais ainda estão pendentes.
Para ambientes de produção, a documentação recomenda gerar um script SQL em vez de rodar database update diretamente. O comando abaixo cria esse script a partir das migrations do projeto.
# gera um script SQL idempotente com todas as migrations
dotnet ef migrations script --idempotent --output migrations.sql
Com isso, a equipe pode revisar o SQL antes de executá-lo no servidor. Além disso, a opção --idempotent permite rodar o mesmo script em bancos que estejam em versões diferentes.
Para seguir estudando, veja o tutorial oficial sobre migrações na Contoso University e o guia de migrações em ambientes de equipe.
Evoluindo o modelo com novas migrations no PostgreSQL
A primeira migration é só o começo, porque o modelo da API muda com o tempo. Por exemplo, imagine que você precise registrar a data de publicação de cada vídeo.
// Models/Video.cs
public class Video
{
public int Id { get; set; }
public string Title { get; set; }
public string Url { get; set; }
public DateTime PublishedAt { get; set; } // nova propriedade
}
Depois de alterar a classe, crie uma nova migration com um nome que descreva a mudança. Em seguida, aplique-a ao banco com o mesmo comando de atualização.
# gera uma migration apenas com a diferença em relação ao snapshot
dotnet ef migrations add AddVideoPublishedAt
# aplica a nova migration ao banco
dotnet ef database update
Nesse momento, o EF Core compara o modelo atual com o snapshot e gera apenas a instrução para adicionar a coluna. Assim, as migrations no PostgreSQL evoluem o esquema sem apagar os dados existentes.
Antes de aplicar, vale abrir o arquivo gerado e conferir o conteúdo. De acordo com a documentação de migrations do EF Core, é uma boa prática revisar e, se necessário, ajustar o que foi gerado.
Revertendo migrations no PostgreSQL
Se uma migration aplicada causar problemas, você pode voltar o banco para um estado anterior. Para isso, informe o nome da migration de destino no comando de atualização.
# volta o banco para o estado da migration InitialCreate
dotnet ef database update InitialCreate
Depois de reverter, o comando dotnet ef migrations remove passa a funcionar para a migration desfeita. Dessa forma, você corrige o modelo e gera uma nova versão sem deixar lixo no histórico.
Erros comuns nas migrations no PostgreSQL
Alguns problemas aparecem com frequência para quem cria migrations no PostgreSQL pela primeira vez. Conhecê-los economiza boas horas de pesquisa.
O primeiro é a ordem dos comandos. Primeiro você cria a migration com migrations add e só depois aplica com database update, pois sem migration não há nada para aplicar.
Outro erro comum é executar os comandos fora da pasta do projeto. Nesse caso, o dotnet ef não encontra o .csproj e falha logo no início.
A versão das ferramentas também importa. A documentação recomenda usar a ferramenta com a mesma versão principal dos pacotes do EF Core, ou seja, 5.x para um projeto no .NET 5.
Por fim, confira usuário, senha, porta e host da string de conexão. Uma falha de autenticação no PostgreSQL costuma aparecer apenas no database update, porque a criação da migration não acessa o banco.
Depois que as migrations estiverem funcionando, o próximo passo natural é implementar as operações da API. O artigo sobre CRUD com Entity Framework ajuda nessa etapa.
Conclusão
Aprender algo novo é sempre um desafio, que exige investimento de tempo e resiliência para lidar com frustrações. Para quem está começando no .NET, encontrar a solução descrita aqui levou um dia inteiro de pesquisa.
Com os pacotes corretos, a string de conexão configurada e a ferramenta dotnet ef instalada, criar migrations no PostgreSQL se resume a dois comandos. Além disso, o mesmo fluxo funciona no Windows, no Linux e no macOS.
Esperamos que este guia ajude você e que inspire a escrever sobre os assuntos que você domina e não encontrou facilmente. Se conhecer formas mais simples de fazer o que mostramos aqui, compartilhe nos comentários.
FAQ
Preciso criar o banco de dados antes de rodar as migrations?
Não. Ao executar dotnet ef database update, o EF Core cria o banco informado na string de conexão, caso ele ainda não exista.
Qual a diferença entre migrations add e database update?
O migrations add gera os arquivos da migration a partir do modelo. Já o database update aplica essas migrations ao banco de dados.
Posso usar o Package Manager Console no macOS?
Não. As ferramentas do Package Manager Console rodam no Visual Studio para Windows, então no macOS use a CLI com dotnet ef.
Qual pacote conecta o EF Core ao PostgreSQL?
O pacote Npgsql.EntityFrameworkCore.PostgreSQL, que fornece o método UseNpgsql. Em projetos no .NET 5, use a versão 5.x.
Como desfazer uma migration criada por engano?
Use dotnet ef migrations remove para apagar a última migration que ainda não foi aplicada. Se ela já foi aplicada, primeiro reverta o banco para a migration anterior.
Existe alternativa ao PostgreSQL sem instalar nada na máquina?
Sim. Você pode rodar o PostgreSQL ou o SQL Server em um contêiner Docker, sem instalação direta no sistema.