Exercício - Configurar uma migração
Nesta unidade, você cria classes de entidade C# que mapeiam para tabelas em um banco de dados SQLite local. O recurso de migrações do EF Core produz tabelas dessas entidades.
Uma migração fornece uma maneira de atualizar incrementalmente o esquema do banco de dados.
Obter os arquivos do projeto
Para começar, obtenha os arquivos do projeto. Você tem algumas opções para como obter os arquivos do projeto:
- Usar Codespaces do GitHub
- Clone o repositório GitHub
Se você tiver um tempo de execução de contêiner compatível instalado, também poderá usar a extensão Dev Containers para abrir o repositório em um contêiner com as ferramentas pré-instaladas.
Usar Codespaces do GitHub
Um espaço de código é um IDE hospedado na nuvem. Se você estiver usando o GitHub Codespaces, vá para o repositório em seu navegador. Selecione Código e, em seguida, crie um novo espaço de main
código na ramificação.
Clone o repositório GitHub
Se você não estiver usando o GitHub Codespaces, poderá clonar o repositório do GitHub do projeto e, em seguida, abrir os arquivos como uma pasta no Visual Studio Code.
Abra um terminal de comando e, em seguida, clone o projeto do GitHub usando o prompt de comando:
git clone https://github.com/MicrosoftDocs/mslearn-persist-data-ef-core
Vá para a pasta mslearn-persist-data-ef-core e, em seguida, abra o projeto no Visual Studio Code:
cd mslearn-persist-data-ef-core code .
Rever o código
Agora que você tem os arquivos de projeto para trabalhar, vamos ver o que há no projeto e revisar o código.
- O projeto de API Web ASP.NET Core está localizado no diretório ContosoPizza . Os caminhos de arquivo aos quais nos referimos neste módulo são relativos ao diretório ContosoPizza .
-
Services/PizzaService.cs é uma classe de serviço que define métodos de criação, leitura, atualização e exclusão (CRUD). Todos os métodos atualmente lançam
System.NotImplementedException
. - Em Program.cs,
PizzaService
está registrado no sistema de injeção de dependência ASP.NET Core. -
Controllers/PizzaController.cs é um valor que
ApiController
expõe um ponto de extremidade para verbos HTTP POST, GET, PUT e DELETE. Esses verbos chamam os métodos CRUD correspondentes emPizzaService
.PizzaService
é injetadoPizzaController
no construtor. - A pasta Modelos contém os modelos que
PizzaService
ePizzaController
usar. - Os modelos de entidade, Pizza.cs, Topping.cs e Sauce.cs, têm as seguintes relações:
- Uma pizza pode ter uma ou mais coberturas.
- Uma cobertura pode ser usada em uma ou em muitas pizzas.
- Uma pizza pode ter um molho, mas um molho pode ser usado em muitas pizzas.
Criar a aplicação
Para criar o aplicativo no Visual Studio Code:
No painel Explorer, clique com o botão direito do mouse no diretório ContosoPizza e selecione Abrir no Terminal Integrado.
Um painel de terminal com escopo para o diretório ContosoPizza é aberto.
Crie o aplicativo usando o seguinte comando:
dotnet build
O código deve ser compilado sem avisos ou erros.
Adicionar pacotes NuGet e ferramentas EF Core
O mecanismo de banco de dados com o qual você trabalha neste módulo é SQLite. SQLite é um mecanismo de banco de dados leve e baseado em arquivo. É uma boa escolha para desenvolvimento e testes, e também é uma boa escolha para implantações de produção em pequena escala.
Nota
Como mencionado anteriormente, os provedores de banco de dados no EF Core podem ser conectados. SQLite é uma boa escolha para este módulo porque é leve e multiplataforma. Você pode usar o mesmo código para trabalhar com diferentes mecanismos de banco de dados, como SQL Server e PostgreSQL. Você pode até mesmo usar vários mecanismos de banco de dados no mesmo aplicativo.
Antes de começar, adicione os pacotes necessários:
No painel de terminal, execute o seguinte comando:
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
Este comando adiciona o pacote NuGet que contém o provedor de banco de dados EF Core SQLite e todas as suas dependências, incluindo os serviços comuns do EF Core.
Em seguida, execute este comando:
dotnet add package Microsoft.EntityFrameworkCore.Design
Este comando adiciona pacotes que são necessários para as ferramentas EF Core.
Para concluir, execute este comando:
dotnet tool install --global dotnet-ef
Este comando instala
dotnet ef
o , a ferramenta que você usa para criar migrações e andaimes.Gorjeta
Se
dotnet ef
já estiver instalado, você pode atualizá-lo executandodotnet tool update --global dotnet-ef
.
Modelos de andaime e DbContext
Agora você adiciona e configura uma DbContext
implementação.
DbContext
é um gateway através do qual você pode interagir com o banco de dados.
Clique com o botão direito do mouse no diretório ContosoPizza e adicione uma nova pasta chamada Dados.
Na pasta Dados, crie um novo arquivo chamado PizzaContext.cs. Adicione o seguinte código ao arquivo vazio:
using Microsoft.EntityFrameworkCore; using ContosoPizza.Models; namespace ContosoPizza.Data; public class PizzaContext : DbContext { public PizzaContext (DbContextOptions<PizzaContext> options) : base(options) { } public DbSet<Pizza> Pizzas => Set<Pizza>(); public DbSet<Topping> Toppings => Set<Topping>(); public DbSet<Sauce> Sauces => Set<Sauce>(); }
No código anterior:
- O construtor aceita um parâmetro do tipo
DbContextOptions<PizzaContext>
. O construtor permite que o código externo passe na configuração para que o mesmoDbContext
possa ser compartilhado entre o código de teste e produção, e até mesmo ser usado com diferentes provedores. - As
DbSet<T>
propriedades correspondem a tabelas a serem criadas no banco de dados. - Os nomes de tabela correspondem aos nomes de
DbSet<T>
PizzaContext
propriedade na classe. Você pode substituir esse comportamento, se necessário. - Quando instanciado,
PizzaContext
expõe asPizzas
propriedades ,Toppings
eSauces
. As alterações feitas nas coleções que essas propriedades expõem são propagadas para o banco de dados.
- O construtor aceita um parâmetro do tipo
No Program.cs, substitua
// Add the PizzaContext
pelo seguinte código:builder.Services.AddSqlite<PizzaContext>("Data Source=ContosoPizza.db");
O código anterior:
- Registra-se
PizzaContext
no sistema de injeção de dependência ASP.NET Core. - Especifica que
PizzaContext
usa o provedor de banco de dados SQLite. - Define uma cadeia de conexão SQLite que aponta para um arquivo local, ContosoPizza.db.
Nota
O SQLite usa arquivos de banco de dados locais, portanto, não há problema em codificar a cadeia de conexão. Para bancos de dados de rede como PostgreSQL e SQL Server, você sempre deve armazenar suas cadeias de conexão com segurança. Para o desenvolvimento local, use o Secret Manager. Para implantações de produção, considere usar um serviço como o Azure Key Vault.
- Registra-se
Também no Program.cs, substitua
// Additional using declarations
pelo código a seguir.using ContosoPizza.Data;
Este código resolve dependências na etapa anterior.
Guarde todas as alterações. O GitHub Codespaces salva suas alterações automaticamente.
Crie o aplicativo no terminal executando
dotnet build
. A compilação deve ser bem-sucedida sem avisos ou erros.
Criar e executar uma migração
Em seguida, crie uma migração que você possa usar para criar seu banco de dados inicial.
No escopo do terminal para a pasta do projeto ContosoPizza , execute o seguinte comando para gerar uma migração para criar as tabelas de banco de dados:
dotnet ef migrations add InitialCreate --context PizzaContext
No comando anterior:
- A migração tem o nome: InitialCreate.
- A opção
--context
especifica o nome da classe no projeto ContosoPizza, que deriva deDbContext
.
É apresentado um novo diretório Migrations na raiz do projeto ContosoPizza. O diretório contém um <timestamp>_InitialCreate.cs arquivo que descreve as alterações do banco de dados a serem traduzidas para um script de alteração DDL (Data Definition Language).
Execute o seguinte comando para aplicar a migração InitialCreate:
dotnet ef database update --context PizzaContext
Este comando aplica a migração. ContosoPizza.db não existe, então este comando cria a migração no diretório do projeto.
Gorjeta
Todas as plataformas suportam a
dotnet ef
ferramenta. No Visual Studio no Windows, você pode usar osAdd-Migration
cmdlets eUpdate-Database
PowerShell na janela integrada do Console do Gerenciador de Pacotes.
Inspecionar o banco de dados
O EF Core criou um banco de dados para seu aplicativo. Em seguida, vamos dar uma olhada dentro do banco de dados usando a extensão SQLite.
No painel Explorer, clique com o botão direito do mouse no arquivo ContosoPizza.db e selecione Abrir Banco de Dados.
Uma pasta SQLite Explorer aparece no painel Explorer.
Selecione a pasta SQLite Explorer para expandir o nó e todos os seus nós filho. Clique com o botão direito do mouse em ContosoPizza.db e selecione Mostrar Tabela 'sqlite_master' para exibir o esquema completo do banco de dados e as restrições que a migração criou.
- Foram criadas tabelas que correspondem a cada entidade.
- Os nomes das tabelas foram retirados dos nomes das
DbSet
propriedades noPizzaContext
. - As propriedades nomeadas
Id
foram inferidas como sendo campos de chave primária de incremento automático. - As convenções de nomenclatura de chave primária e restrição de chave estrangeira do EF Core são
PK_<primary key property>
eFK_<dependent entity>_<principal entity>_<foreign key property>
, respectivamente. Os marcadores de posição<dependent entity>
e<principal entity>
correspondem aos nomes das classes de entidades.
Nota
Como ASP.NET MVC Core, o EF Core usa uma abordagem de convenção sobre configuração . As convenções do EF Core reduzem o tempo de desenvolvimento ao inferirem a intenção do programador. Por exemplo, o núcleo do EF infere uma propriedade chamada
Id
ou<entity name>Id
que seja a chave primária da tabela gerada. Se você optar por não adotar a convenção de nomenclatura, deverá anotar a propriedade com o[Key]
atributo ou configurá-la como uma chave noOnModelCreating
método doDbContext
.
Alterar o modelo e atualizar o esquema do banco de dados
Seu gerente na Contoso Pizza fornece alguns novos requisitos, portanto, você precisa alterar seus modelos de entidade. Nas etapas a seguir, você modifica os modelos usando atributos de mapeamento (às vezes chamados de anotações de dados).
Em Modelos\Pizza.cs, faça as seguintes alterações:
- Adicione uma
using
diretiva paraSystem.ComponentModel.DataAnnotations
. - Adicione um
[Required]
atributo antes daName
propriedade para marcá-la como necessária. - Adicione um
[MaxLength(100)]
atributo antes daName
propriedade para especificar um comprimento máximo de cadeia de caracteres de 100.
Seu arquivo de Pizza.cs atualizado deve se parecer com o seguinte código:
using System.ComponentModel.DataAnnotations; namespace ContosoPizza.Models; public class Pizza { public int Id { get; set; } [Required] [MaxLength(100)] public string? Name { get; set; } public Sauce? Sauce { get; set; } public ICollection<Topping>? Toppings { get; set; } }
- Adicione uma
Em Modelos\Sauce.cs, faça as seguintes alterações:
- Adicione uma
using
diretiva paraSystem.ComponentModel.DataAnnotations
. - Adicione um
[Required]
atributo antes daName
propriedade para marcá-la como necessária. - Adicione um
[MaxLength(100)]
atributo antes daName
propriedade para especificar um comprimento máximo de cadeia de caracteres de 100. - Adicione uma
bool
propriedade chamadaIsVegan
.
Seu arquivo de Sauce.cs atualizado deve se parecer com o seguinte código:
using System.ComponentModel.DataAnnotations; namespace ContosoPizza.Models; public class Sauce { public int Id { get; set; } [Required] [MaxLength(100)] public string? Name { get; set; } public bool IsVegan { get; set; } }
- Adicione uma
Em Modelos\Topping.cs, faça as seguintes alterações:
Adicionar
using
diretivas paraSystem.ComponentModel.DataAnnotations
eSystem.Text.Json.Serialization
.Adicione um
[Required]
atributo antes daName
propriedade para marcá-la como necessária.Adicione um
[MaxLength(100)]
atributo antes daName
propriedade para especificar um comprimento máximo de cadeia de caracteres de 100.Adicione uma
decimal
propriedade com o nomeCalories
imediatamente após aName
propriedade.Adicione uma
Pizzas
propriedade do tipoICollection<Pizza>?
. Esta mudança criaPizza
-Topping
uma relação muitos-para-muitos.Adicione um
[JsonIgnore]
atributo àPizzas
propriedade.Importante
Esse atributo impede que
Topping
as entidades incluam aPizzas
propriedade quando o código da API da Web serializa a resposta para JSON. Sem essa alteração, uma coleção serializada de coberturas incluiria uma coleção de cada pizza que usa a cobertura. Cada pizza dessa coleção conteria uma coleção de coberturas, cada uma contendo novamente uma coleção de pizzas. Esse tipo de loop infinito é chamado de referência circular e não pode ser serializado.
Seu arquivo de Topping.cs atualizado deve se parecer com o seguinte código:
using System.ComponentModel.DataAnnotations; using System.Text.Json.Serialization; namespace ContosoPizza.Models; public class Topping { public int Id { get; set; } [Required] [MaxLength(100)] public string? Name { get; set; } public decimal Calories { get; set; } [JsonIgnore] public ICollection<Pizza>? Pizzas { get; set; } }
Salve todas as suas alterações e execute
dotnet build
.Execute o seguinte comando para gerar uma migração para criar as tabelas de base de dados:
dotnet ef migrations add ModelRevisions --context PizzaContext
Este comando cria uma migração com o nome: ModelRevisions.
Nota
Você verá esta mensagem: Uma operação foi estruturada que pode resultar na perda de dados. Por favor, revise a migração para obter precisão. Essa mensagem apareceu porque você alterou a relação de
Pizza
um-para-muitosTopping
para muitos, o que requer que uma coluna de chave estrangeira existente seja descartada. Como você ainda não tem nenhum dado em seu banco de dados, essa alteração não é problemática. No entanto, em geral, é uma boa ideia verificar a migração gerada quando esse aviso aparecer para garantir que a migração não exclua ou trunce nenhum dado.Execute o seguinte comando para aplicar a migração ModelRevisions:
dotnet ef database update --context PizzaContext
Na barra de título da pasta SQLite Explorer , selecione o botão Atualizar bancos de dados .
Na pasta SQLite Explorer, clique com o botão direito do mouse em ContosoPizza.db. Selecione Mostrar tabela 'sqlite_master' para visualizar o esquema e as restrições do banco de dados completo.
Importante
A extensão SQLite reutiliza guias SQLite abertas.
- Uma
PizzaTopping
mesa de junção foi criada para representar a relação muitos-para-muitos entre pizzas e coberturas. - Novos campos foram adicionados a
Toppings
eSauces
.-
Calories
é definido como umatext
coluna porque o SQLite não tem um tipo correspondentedecimal
. - Da mesma forma,
IsVegan
é definido como umainteger
coluna. SQLite não define umbool
tipo. - Em ambos os casos, o EF Core gerencia a tradução.
-
- A
Name
coluna em cada tabela foi marcadanot null
, mas o SQLite não tem umaMaxLength
restrição.
Gorjeta
Os provedores de banco de dados EF Core mapeiam um esquema de modelo para os recursos de um banco de dados específico. Embora o SQLite não implemente uma restrição correspondente para
MaxLength
o , outros bancos de dados como SQL Server e PostgreSQL o fazem.- Uma
Na pasta SQLite Explorer, clique com o botão direito do mouse na
_EFMigrationsHistory
tabela e selecione Mostrar tabela. A tabela contém uma lista de todas as migrações aplicadas ao banco de dados. Como você executou duas migrações, há duas entradas: uma para a migração InitialCreate e outra para ModelRevisions.
Nota
Este exercício usou atributos de mapeamento (anotações de dados) para mapear modelos para o banco de dados. Como alternativa ao mapeamento de atributos, você pode usar a API fluente do ModelBuilder para configurar modelos. Ambas as abordagens são válidas, mas alguns desenvolvedores preferem uma abordagem em detrimento da outra.
Você usou migrações para definir e atualizar um esquema de banco de dados. Na próxima unidade, você concluirá os métodos em PizzaService
que manipular dados.