Tutorial: Parte 5, aplicar migrações ao exemplo da Contoso University

Neste tutorial, você começa usando o recurso de migrações do EF Core para o gerenciamento de alterações do modelo de dados. Em tutoriais seguintes, você adicionará mais migrações conforme você alterar o modelo de dados.

Neste tutorial, você:

  • Aprenderá sobre migrações
  • Criar uma migração inicial
  • Examinará os métodos Up e Down
  • Aprenderá sobre o instantâneo do modelo de dados
  • Aplicar a migração

Pré-requisitos

Sobre migrações

Quando você desenvolve um novo aplicativo, o modelo de dados é alterado com frequência e, sempre que o modelo é alterado, ele fica fora de sincronia com o banco de dados. Você começou estes tutoriais configurando o Entity Framework para criar o banco de dados, caso ele não exista. Em seguida, sempre que você alterar o modelo de dados – adicionar, remover, alterar classes de entidade ou alterar a classe DbContext –, poderá excluir o banco de dados e o EF criará um novo que corresponde ao modelo e o propagará com os dados de teste.

Esse método de manter o banco de dados em sincronia com o modelo de dados funciona bem até que você implante o aplicativo em produção. Quando o aplicativo é executado em produção, ele normalmente armazena os dados que você deseja manter, e você não quer perder tudo sempre que fizer uma alteração, como a adição de uma nova coluna. O recurso Migrações do EF Core resolve esse problema, permitindo que o EF atualize o esquema de banco de dados em vez de criar um novo banco de dados.

Para trabalhar com migrações, use o PMC (Console do Gerenciador de Pacotes) ou a CLI. Esses tutoriais mostram como usar comandos da CLI. Encontre informações sobre o PMC no final deste tutorial.

Remover o banco de dados

Instale ferramentas EF Core como uma ferramenta global e exclua o banco de dados:

dotnet tool install --global dotnet-ef
dotnet ef database drop

Observação

Por padrão, a arquitetura dos binários do .NET a serem instalados representa a arquitetura do SO sendo executado no momento. Para especificar uma arquitetura de SO diferente, consulte instalação da ferramenta dotnet, opção --arch. Para obter mais informações, confira o problema dotnet/AspNetCore.Docs #29262 do GitHub.

A seção a seguir explica como executar comandos da CLI.

Criar uma migração inicial

Salve as alterações e compile o projeto. Em seguida, abra uma janela Comando e navegue para a pasta do projeto. Esta é uma maneira rápida de fazer isso:

  • No Gerenciador de Soluções, clique com o botão direito do mouse no projeto e escolha Abrir Pasta no Explorador de Arquivos no menu de contexto.

    Open in File Explorer menu item

  • Insira "cmd" na barra de endereços e pressione Enter.

    Open command window

Insira o seguinte comando na janela de comando:

dotnet ef migrations add InitialCreate

Nos comandos anteriores, uma saída semelhante à seguinte é exibida:

info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core initialized 'SchoolContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
Done. To undo this action, use 'ef migrations remove'

Se você receber uma mensagem de erro "Não é possível acessar o arquivo... ContosoUniversity.dll porque está sendo usado por outro processo.", localize o ícone do IIS Express na Bandeja do Sistema do Windows e clique com o botão direito do mouse nele e clique em ContosoUniversity > Parar Site.

Examinará os métodos Up e Down

Quando você executou o comando migrations add, o EF gerou o código que criará o banco de dados do zero. Esse código está localizado na pasta Migrations, no arquivo chamado <timestamp>_InitialCreate.cs. O método Up da classe InitialCreate cria as tabelas de banco de dados que correspondem aos conjuntos de entidades do modelo de dados, e o método Down exclui-as, conforme mostrado no exemplo a seguir.

public partial class InitialCreate : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Course",
            columns: table => new
            {
                CourseID = table.Column<int>(nullable: false),
                Credits = table.Column<int>(nullable: false),
                Title = table.Column<string>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Course", x => x.CourseID);
            });

        // Additional code not shown
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "Enrollment");
        // Additional code not shown
    }
}

As migrações chamam o método Up para implementar as alterações do modelo de dados para uma migração. Quando você insere um comando para reverter a atualização, as Migrações chamam o método Down.

Esse código destina-se à migração inicial que foi criada quando você inseriu o comando migrations add InitialCreate. O parâmetro de nome da migração ("InitialCreate" no exemplo) é usado para o nome do arquivo e pode ser o que você desejar. É melhor escolher uma palavra ou frase que resume o que está sendo feito na migração. Por exemplo, você pode nomear uma migração posterior "AddDepartmentTable".

Se você criou a migração inicial quando o banco de dados já existia, o código de criação de banco de dados é gerado, mas ele não precisa ser executado porque o banco de dados já corresponde ao modelo de dados. Quando você implantar o aplicativo em outro ambiente no qual o banco de dados ainda não existe, esse código será executado para criar o banco de dados; portanto, é uma boa ideia testá-lo primeiro. É por isso que você removeu o banco de dados anteriormente – para que as migrações possam criar um novo do zero.

O instantâneo do modelo de dados

As migrações criam um instantâneo do esquema de banco de dados atual em Migrations/SchoolContextModelSnapshot.cs. Quando você adiciona uma migração, o EF determina o que foi alterado, comparando o modelo de dados com o arquivo de instantâneo.

Use o comando dotnet ef migrations remove pra remover uma migração. dotnet ef migrations remove exclui a migração e garante que o instantâneo seja redefinido corretamente. Se dotnet ef migrations remove falhar, use dotnet ef migrations remove -v para obter mais informações sobre a falha.

Confira Migrações do EF Core em ambientes de equipe para obter mais informações de como o arquivo de instantâneo é usado.

Aplicar a migração

Na janela Comando, insira o comando a seguir para criar o banco de dados e tabelas nele.

dotnet ef database update

A saída do comando é semelhante ao comando migrations add, exceto que os logs para os comandos SQL que configuram o banco de dados são exibidos. A maioria dos logs é omitida na seguinte saída de exemplo. Se você preferir não ver esse nível de detalhe em mensagens de log, altere o nível de log no arquivo appsettings.Development.json. Para obter mais informações, confira Log no .NET Core e no ASP.NET Core.

info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core initialized 'SchoolContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (274ms) [Parameters=[], CommandType='Text', CommandTimeout='60']
      CREATE DATABASE [ContosoUniversity2];
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (60ms) [Parameters=[], CommandType='Text', CommandTimeout='60']
      IF SERVERPROPERTY('EngineEdition') <> 5
      BEGIN
          ALTER DATABASE [ContosoUniversity2] SET READ_COMMITTED_SNAPSHOT ON;
      END;
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (15ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      CREATE TABLE [__EFMigrationsHistory] (
          [MigrationId] nvarchar(150) NOT NULL,
          [ProductVersion] nvarchar(32) NOT NULL,
          CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId])
      );

<logs omitted for brevity>

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
      VALUES (N'20190327172701_InitialCreate', N'5.0-rtm');
Done.

Use o Pesquisador de Objetos do SQL Server para inspecionar o banco de dados como você fez no primeiro tutorial. Você observará a adição de uma tabela __EFMigrationsHistory que controla quais migrações foram aplicadas ao banco de dados. Exiba os dados dessa tabela e você verá uma linha para a primeira migração. (O último log no exemplo de saída da CLI anterior mostra a instrução INSERT que cria essa linha.)

Execute o aplicativo para verificar se tudo ainda funciona como antes.

Students Index page

Comparar CLI e PMC

As ferramentas do EF para gerenciamento de migrações estão disponíveis por meio dos comandos da CLI do .NET Core ou de cmdlets do PowerShell na janela PMC (Console do Gerenciador de Pacotes) do Visual Studio. Este tutorial mostra como usar a CLI, mas você poderá usar o PMC se preferir.

Os comandos do EF para os comandos do PMC estão no pacote Microsoft.EntityFrameworkCore.Tools. Esse pacote está incluído no metapacote Microsoft.AspNetCore.App, portanto você não precisa adicionar uma referência de pacote se o aplicativo tem uma referência de pacote ao Microsoft.AspNetCore.App.

Importante: esse não é o mesmo pacote que é instalado para a CLI com a edição do arquivo .csproj. O nome deste termina com Tools, ao contrário do nome do pacote da CLI que termina com Tools.DotNet.

Para obter mais informações sobre os comandos da CLI, consulte CLI do .NET Core.

Para obter mais informações sobre os comandos do PMC, consulte Console do Gerenciador de Pacotes (Visual Studio).

Obter o código

Baixe ou exiba o aplicativo concluído.

Próxima etapa

Vá para o próximo tutorial para começar a examinar tópicos mais avançados sobre a expansão do modelo de dados. Ao longo do processo, você criará e aplicará migrações adicionais.