Övning – Konfigurera en migrering

Slutförd

I den här lektionen skapar du C#-entitetsklasser som mappas till tabeller i en lokal SQLite-databas. Funktionen EF Core-migrering skapar tabeller från dessa entiteter.

En migrering är ett sätt att stegvis uppdatera databasschemat.

Hämta projektfilerna

Kom igång genom att hämta projektfilerna. Du har några alternativ för hur du hämtar projektfilerna:

  • Använda GitHub Codespaces
  • Klona GitHub-lagringsplatsen

Om du har en kompatibel containerkörning installerad kan du även använda Tillägget Dev Containers för att öppna lagringsplatsen i en container med verktygen förinstallerade.

Använda GitHub Codespaces

Ett kodområde är en IDE som finns i molnet. Om du använder GitHub Codespaces går du till lagringsplatsen i webbläsaren. Välj Kod och skapa sedan ett nytt kodområde i -grenen main .

Klona GitHub-lagringsplatsen

Om du inte använder GitHub Codespaces kan du klona projektets GitHub-lagringsplats och sedan öppna filerna som en mapp i Visual Studio Code.

  1. Öppna en kommandoterminal och klona sedan projektet från GitHub med hjälp av kommandotolken:

    git clone https://github.com/MicrosoftDocs/mslearn-persist-data-ef-core
    
  2. Gå till mappen mslearn-persist-data-ef-core och öppna projektet i Visual Studio Code:

    cd mslearn-persist-data-ef-core
    code .
    

Granska koden

Nu har du projektfilerna att arbeta med. Se vad som finns i projektet och granska koden.

  • Projektet, ett ASP.NET Core webb-API, finns i katalogen ContosoPizza. De filsökvägar som refereras till i den här modulen är relativa till ContosoPizza-katalogen .
  • Services/PizzaService.cs är en tjänstklass som definierar CRUD-metoder (create, read, update och delete). Alla metoder genererar System.NotImplementedExceptionför närvarande .
  • I Program.csPizzaService registreras med ASP.NET Core beroendeinmatningssystemet.
  • Controllers/PizzaController.cs är ett värde för ApiController som exponerar en slutpunkt för HTTP POST-, GET-, PUT- och DELETE-verb. Dessa verb anropar motsvarande CRUD-metoder på PizzaService. PizzaService matas in i PizzaController konstruktorn.
  • Mappen Modeller innehåller de modeller som används av PizzaService och PizzaController.
  • Entitetsmodellerna Pizza.cs, Topping.cs och Sauce.cs har följande relationer:
    • En pizza kan ha en eller flera pålägg.
    • En topping kan användas på en eller flera pizzor.
    • En pizza kan ha en sås, men en sås kan användas på många pizzor.

Skapa appen

Så här skapar du appen i Visual Studio Code:

  1. Högerklicka på katalogen ContosoPizza i Explorer-fönstret och välj Öppna i integrerad terminal.

    Ett terminalfönster som är begränsat till ContosoPizza-katalogen öppnas.

  2. Skapa appen med hjälp av följande kommando:

    dotnet build
    

    Koden bör skapas utan varningar eller fel.

Lägga till NuGet-paket och EF Core-verktyg

Databasmotorn som du arbetar med i den här modulen är SQLite. SQLite är en enkel, filbaserad databasmotor. Det är ett bra val för utveckling och testning, och det är också ett bra val för småskaliga produktionsdistributioner.

Anteckning

Som tidigare nämnts är databasprovidrar i EF Core anslutningsbara. SQLite är ett bra alternativ för den här modulen eftersom den är enkel och plattformsoberoende. Du kan använda samma kod för att arbeta med olika databasmotorer, till exempel SQL Server och PostgreSQL. Du kan till och med använda flera databasmotorer i samma app.

Innan du börjar lägger du till de nödvändiga paketen:

  1. Kör följande kommando i terminalfönstret:

    dotnet add package Microsoft.EntityFrameworkCore.Sqlite
    

    Det här kommandot lägger till NuGet-paketet som innehåller EF Core SQLite-databasprovidern och alla dess beroenden, inklusive de vanliga EF Core-tjänsterna.

  2. Kör följande kommando:

    dotnet add package Microsoft.EntityFrameworkCore.Design
    

    Det här kommandot lägger till paket som krävs för EF Core-verktygen.

  3. Slutför genom att köra det här kommandot:

    dotnet tool install --global dotnet-ef
    

    Det här kommandot installerar dotnet ef, det verktyg som du använder för att skapa migreringar och autogenerering.

    Tips

    Om dotnet ef redan är installerat kan du uppdatera det genom att köra dotnet tool update --global dotnet-ef.

Autogenerera modeller och DbContext

Nu lägger du till och konfigurerar en DbContext implementering. DbContext är en gateway som du kan interagera med databasen genom.

  1. Högerklicka på katalogen ContosoPizza och lägg till en ny mapp med namnet Data.

  2. I mappen Data skapar du en ny fil med namnet PizzaContext.cs. Lägg till följande kod i den tomma filen:

    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>();
    }
    

    I koden ovan:

    • Konstruktorn accepterar en parameter av typen DbContextOptions<PizzaContext>. Konstruktorn tillåter att extern kod skickar konfigurationen så att samma DbContext kan delas mellan test- och produktionskod och även användas med olika providers.
    • Egenskaperna DbSet<T> motsvarar tabeller som ska skapas i databasen.
    • Tabellnamnen matchar DbSet<T>-egenskapsnamnen i klassen PizzaContext. Du kan åsidosätta det här beteendet om det behövs.
    • När instansieras PizzaContext exponeras Pizzasegenskaperna , Toppingsoch Sauces . Ändringar som du gör i de samlingar som exponeras av dessa egenskaper kommer att spridas till databasen.
  3. I Program.cs ersätter du // Add the PizzaContext med följande kod:

    builder.Services.AddSqlite<PizzaContext>("Data Source=ContosoPizza.db");
    

    Koden ovan:

    • PizzaContext Registrerar med ASP.NET Core beroendeinmatningssystemet.
    • Anger att PizzaContext ska använda SQLite-databasprovidern.
    • Definierar en SQLite-anslutningssträng som pekar på en lokal fil, ContosoPizza.db.

    Anteckning

    SQLite använder lokala databasfiler, så det är förmodligen okej att hårdkoda anslutningssträngen. För nätverksdatabaser som PostgreSQL och SQL Server bör du alltid lagra anslutningssträngarna på ett säkert sätt. Använd Secret Manager för lokal utveckling. Överväg att använda en tjänst som Azure Key Vault för produktionsdistributioner.

  4. Ersätt även i Program.cs// Additional using declarations med följande kod.

    using ContosoPizza.Data;
    

    Den här koden löser beroenden i föregående steg.

  5. Spara alla ändringar. GitHub Codespaces sparar ändringarna automatiskt.

  6. Skapa appen i terminalen genom att köra dotnet build. Bygget bör lyckas utan varningar eller fel.

Skapa och köra en migrering

Skapa sedan en migrering som du kan använda för att skapa din första databas.

  1. Kör följande kommando för att skapa en migrering för generering av databastabellerna:

    dotnet ef migrations add InitialCreate --context PizzaContext
    

    I kommandot ovan:

    • Migreringen ges namnet InitialCreate.
    • Alternativet --context anger namnet på klassen i projektet ContosoPizza, som härleds från DbContext.

    En ny Migrations-katalog visas i ContosoPizza-projektroten. Katalogen innehåller en <timestamp>_InitialCreate.cs fil som beskriver databasändringarna som ska översättas till ett DDL-ändringsskript (Data Definition Language).

  2. Tillämpa InitialCreate-migreringen genom att köra följande kommando:

    dotnet ef database update --context PizzaContext
    

    Det här kommandot tillämpar migreringen. ContosoPizza.db finns inte, så migreringen skapas i projektkatalogen.

    Tips

    dotnet ef-verktyget stöds på alla plattformar. I Visual Studio i Windows kan du använda Add-Migration powershell-cmdletarna och Update-Database i det integrerade package manager-konsolfönstret .

Granska databasen

EF Core skapade en databas för din app. Ta sedan en titt i databasen med hjälp av SQLite-tillägget.

  1. Högerklicka på filen ContosoPizza.db i Explorer-fönstret och välj Öppna databas.

    Skärmbild som visar menyalternativet Öppna databas i Visual Studio Code Explorer-fönstret.

    En SQLite Explorer-mapp visas i Explorer-fönstret .

    Skärmbild som visar mappen SQLite Explorer i utforskarfönstret.

  2. Välj mappen SQLite Explorer för att expandera noden och alla dess underordnade noder. Högerklicka på ContosoPizza.db och välj Visa tabell sqlite_master för att visa det fullständiga databasschemat och begränsningarna som migreringen skapade.

    Skärmbild som visar den expanderade mappen SQLite Explorer i utforskarfönstret.

    • Tabeller som motsvarar varje entitet skapades.
    • Tabellnamn hämtades från namnen DbSet på egenskaperna på PizzaContext.
    • Egenskaper med namnet Id härleddes som autoincrementing av primärnyckelfält.
    • Namngivningskonventionerna för EF Core-primärnyckel och sekundärnyckelvillkor är PK_<primary key property> respektive FK_<dependent entity>_<principal entity>_<foreign key property>. Platshållarna <dependent entity> och <principal entity> motsvarar namnen på entitetsklasser.

    Anteckning

    Precis som ASP.NET Core MVC använder EF Core en konvention över konfigurationsmetod. EF Core-konventioner förkortar utvecklingstiden genom att tolka utvecklarens avsikt. Exempelvis tolkas en egenskap med namnet Id eller <entity name>Id som den genererade tabellens primärnyckel. Om du väljer att inte använda namngivningskonventionen måste egenskapen kommenteras med [Key] attributet eller konfigureras som en nyckel i OnModelCreating metoden för DbContext.

Ändra modellen och uppdatera databasschemat

Din chef på Contoso Pizza ger dig några nya krav, så du måste ändra dina entitetsmodeller. I följande steg ändrar du modellerna med hjälp av mappningsattribut (kallas ibland dataanteckningar).

  1. I Models\Pizza.cs gör du följande ändringar:

    1. Lägg till ett using direktiv för System.ComponentModel.DataAnnotations.
    2. Lägg till ett [Required] attribut före Name egenskapen för att markera egenskapen efter behov.
    3. Lägg till ett [MaxLength(100)] attribut före Name egenskapen för att ange en maximal stränglängd på 100.
    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; }
    }
    
  2. I Models\Sauce.cs gör du följande ändringar:

    1. Lägg till ett using direktiv för System.ComponentModel.DataAnnotations.
    2. Lägg till ett [Required] attribut före Name egenskapen för att markera egenskapen efter behov.
    3. Lägg till ett [MaxLength(100)] attribut före Name egenskapen för att ange en maximal stränglängd på 100.
    4. Lägg till en bool egenskap med namnet IsVegan.
    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; }
    }
    
  3. I Models\Topping.cs gör du följande ändringar:

    1. Lägg till using direktiv för System.ComponentModel.DataAnnotations och System.Text.Json.Serialization.
    2. Lägg till ett [Required] attribut före Name egenskapen för att markera egenskapen efter behov.
    3. Lägg till ett [MaxLength(100)] attribut före Name egenskapen för att ange en maximal stränglängd på 100.
    4. Lägg till en decimal egenskap med namnet Calories direkt efter Name egenskapen .
    5. Lägg till en Pizzas egenskap av typen ICollection<Pizza>? för att skapa Pizza-Topping en många-till-många-relation.
    6. Lägg till ett [JsonIgnore] attribut i egenskapen Pizzas .

    Viktigt

    De här stegen förhindrar Topping att entiteter inkluderar Pizzas egenskapen när webb-API-koden serialiserar svaret på JSON. Utan den här ändringen skulle en serialiserad samling toppings innehålla en samling av varje pizza som använder toppingen. Varje pizza i den samlingen skulle innehålla en samling pålägg, som var och en återigen skulle innehålla en samling pizzor. Den här typen av oändlig loop kallas en cirkelreferens och kan inte serialiseras.

    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; }
    }
    
  4. Spara alla ändringar och kör dotnet build.

  5. Kör följande kommando för att skapa en migrering för generering av databastabellerna:

    dotnet ef migrations add ModelRevisions --context PizzaContext
    

    En migrering med namnet ModelRevisions skapas.

    Anteckning

    Det här meddelandet visas: En åtgärd har autogenererats som kan leda till dataförlust. Granska migreringen för korrekthet. Meddelandet visas eftersom du har ändrat relationen från Pizza till Topping från en-till-många till många-till-många, vilket kräver att en befintlig sekundärnyckelkolumn tas bort. Eftersom du ännu inte har några data i databasen är den här ändringen inte problematisk. I allmänhet är det dock en bra idé att kontrollera den genererade migreringen när den här varningen verkar se till att inga data tas bort eller trunkeras av migreringen.

  6. Tillämpa ModelRevisions-migreringen genom att köra följande kommando:

    dotnet ef database update --context PizzaContext
    
  7. I namnlisten i mappen SQLite Explorer väljer du knappen Uppdatera databaser .

    Skärmbild som visar knappen Uppdatera databaser i namnlisten i SQLite Explorer.

  8. Högerklicka på ContosoPizza.db i mappen SQLite Explorer. Välj Visa tabell "sqlite_master" för att visa det fullständiga databasschemat och begränsningarna.

    Viktigt

    SQLite-tillägget återanvänder öppna SQLite-flikar .

    • En PizzaTopping kopplingstabell skapades för att representera många-till-många-relationen mellan pizzor och pålägg.
    • Nya fält har lagts till Toppings i och Sauces.
      • Calories definieras som en text kolumn eftersom SQLite inte har någon matchande decimal typ.
      • IsVegan På samma sätt definieras som en integer kolumn. SQLite definierar bool ingen typ.
      • I båda fallen hanterar EF Core översättningen.
    • Kolumnen Name i varje tabell har markerats not null, men SQLite har MaxLength ingen begränsning.

    Tips

    EF Core-databasprovidrar mappar ett modellschema till funktionerna i en specifik databas. Även om SQLite inte implementerar någon motsvarande begränsning för MaxLength, gör andra databaser som SQL Server och PostgreSQL.

  9. Högerklicka på _EFMigrationsHistory tabellen i mappen SQLite Explorer och välj Visa tabell. Tabellen innehåller en lista över alla migreringar som tillämpas på databasen. Eftersom du har kört två migreringar finns det två poster: en för migreringen InitialCreate och en annan för ModelRevisions.

Anteckning

I den här övningen användes mappningsattribut (dataanteckningar) för att mappa modeller till databasen. Som ett alternativ till mappningsattribut kan du använda Api:et ModelBuilder fluent för att konfigurera modeller. Båda metoderna är giltiga, men vissa utvecklare föredrar en metod framför den andra.

Du har använt migreringar för att definiera och uppdatera ett databasschema. I nästa lektion slutför du metoderna i PizzaService dessa manipulerade data.

Kontrollera dina kunskaper

1.

Vad är namngivningskonventionen för egenskaper för en primärnyckel i en entitetsklass?