EF Core 6  - Apresentando Migration Bundles


Hoje vou apresentar o novo recurso do EF Core 6 - Migration Bundles - disponível a partir do .NET 6.

O novo recurso do EF Core chamado Migration Bundle é um executável independente com tudo o que é necessário para executar uma migração. Ele aceita a string de conexão como parâmetro e destina-se a ser um artefato usado na implantação contínua que funciona com todas as principais ferramentas (Docker, SSH, PowerShell, etc.).

Um grande benefício de usar o EF Core é a capacidade de gerenciar alterações de esquema por meio de um mecanismo chamado Migrations ou migrações.

Uma migração é essencialmente um mini-instantâneo de um “point-in-time” do seu modelo de banco de dados. Depois de fazer modificações em seu modelo que podem alterar o esquema, você pode usar o EF Core Command Line Interface (CLI) para capturar o instantâneo em uma migração. A mesma ferramenta pode ser usada para apontar uma migração em um banco de dados existente e implantar a linguagem de definição de dados (DDL) necessária para sincronizar o banco de dados com o modelo.

Até agora, quando usamos o EF Core, na maioria das vezes usamos as instruções dotnet ef migrations add <script> e dotnet ef database update para atualizar o banco de dados.

O novo recurso proposto pela equipe do EF Core é criar um executável contendo os scripts de migração e assim que ele for executado ele atualizará o banco de dados.

Vamos testar este recurso - EF Core Migration Bundles -  e, para isso, vamos precisar usar no mínimo a versão EF Core 6 da ferramenta.

Assim, se você ainda não possui a ferramenta instalada use o seguinte comando: (No ambiente do .NET 6)

dotnet tool install --global dotnet-ef 

Se já tiver a ferramenta instalada então use o comando a seguir:

dotnet tool update --global dotnet-ef 

No meu ambiente vou usar o comando acima:

Após instalar a ferramenta no seu ambiente, emita o comando :  dotnet ef migrations bundle -h

Você deverá uma variedade de opções neste recurso que poderá usar:

Para mostrar como o Migrations Bundle funciona vamos usar um projeto Console chamado EFCore6_MIgrationBundle onde temos duas entidades Categoria e Produto e um arquivo de contexto AppDbContext definidos no arquivo Program:

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    {
        services
            .AddDbContext<AppDbContext>(options =>
            {
                options.UseSqlServer(hostContext.Configuration.GetConnectionString("DefaultConnection"));
            });
    })
    .Build();

await host.RunAsync();

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
    public DbSet<Categoria> Categorias { get; set; }
    public DbSet<Produto> Produtos { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Categoria>(builder =>
        {
            builder
                .HasMany(x => x.Produtos)
                .WithOne()
                .HasForeignKey(x => x.CategoriaId);
        });

        modelBuilder.Entity<Categoria>()
         .Property(p => p.Nome)
         .HasMaxLength(100);

    }
}
public class Categoria
{
    public int Id { get; set; }
    public string? Nome { get; set; }
    public ICollection<Produto>? Produtos { get; set; }
}
public class Produto
{
    public int Id { get; set; }
    public string? Nome { get; set; }
    public string? Descricao { get; set; }
    public int CategoriaId { get; set; }
}

E no arquivo appsettings.json temos a string de conexão com o banco de dados BundleDB do SQL Server.

{
  "ConnectionStrings": {
    "DefaultConnection": "<sua_instancia>;Initial Catalog=BundleDB;Integrated Security=True"
  }
}

Vamos abrir uma janela de comandos usando o PowerShell e a seguir vamos entrar na pasta do projeto em : d:\_net6\EFCore6_MigrationBundle\EFCore6_MigrationBundle\

A seguir vamos criar algumas migrações para depois gerar o migrations bundle.

Para criar a primeira migração vamos emitir o comando para criar uma migração inicial :

dotnet ef migrations add Inicial

A seguir vamos ajustar o tamanho das propriedades do tipo String usando a Fluent API e a seguir vamos criar outra migração para evitar a definição das colunas com nvarchar(max) usando o seguinte comando:

dotnet ef migrations add AjusteStrings

A seguir vamos incluir a propriedade Preco na entidade Produto e criar outra migração usando o comando:

dotnet ef migrations add IncluiPrecoProduto

Vamos agora ajustar a propriedade Preco que foi incluída definindo uma precisão de 14 dígitos com 2 casas decimais usando o comando:

dotnet ef migrations add AjustePrecisaoPreco

Neste momento na pasta Migrations do projeto veremos as 4 migrações que foram criadas e que estão pendentes:

Podemos confirmar emitindo o comando :

dotnet ef migrations list

Essas migrações foram criadas mas não foram aplicadas. Assim agora vamos aplicar o Migration Bundle que vai verificar as migrações pendentes e criar o arquivo .exe contendo essas migrações que poderemos executar. Para isso vamos emitir o seguinte comando:

dotnet ef migrations bundle

Observe que foi criado o arquivo efbundle.exe na pasta do projeto :

Agora podemos executar o arquivo gerado e as migrações pendentes serão aplicadas :

E poderemos verificar que o banco de dados e as tabelas foram criadas e ajustadas conforme as migrações que criamos.

Pegue o projeto aqui : EFCore6_MIgrationBundle.zip (sem as referências e o bundle)

"Disse-lhe Jesus: Porque me viste, Tomé, creste; bem-aventurados os que não viram e creram."
João 20:29

Referências:


José Carlos Macoratti