Övning – Konfigurera en migrering

Slutförd

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

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

Hämta projektfilerna

Hämta projektfilerna för att komma igång. 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 också använda Dev Containers-tillägget 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 sedan projektet i Visual Studio Code:

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

Granska koden

Nu när du har projektfilerna att arbeta med ska vi se vad som finns i projektet och granska koden.

  • Webb-API-projektet ASP.NET Core finns i katalogen ContosoPizza . De filsökvägar som vi refererar till i den här modulen är relativa till katalogen ContosoPizza .
  • 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 PizzaService och PizzaController använder.
  • 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 på många pizzor.
    • En pizza kan ha en sås, men en sås kan användas på många pizzor.

Bygga appen

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

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

    Ett terminalfönster som är begränsat till katalogen ContosoPizza ö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.

Kommentar

Som tidigare nämnts kan databasprovidrar i EF Core anslutas. SQLite är ett bra val 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 sedan det här kommandot:

    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 byggnadsställningar.

    Dricks

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

Scaffold-modeller och DbContext

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

  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 skickas i konfigurationen så att samma DbContext kan delas mellan test- och produktionskod och även användas med olika leverantörer.
    • Egenskaperna DbSet<T> motsvarar tabeller som ska skapas i databasen.
    • Tabellnamnen matchar egenskapsnamnen DbSet<T> PizzaContext i klassen. 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 dessa egenskaper exponerar sprids 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 som PizzaContext använder SQLite-databasprovidern.
    • Definierar en SQLite-anslutningssträng som pekar på en lokal fil, ContosoPizza.db.

    Kommentar

    SQLite använder lokala databasfiler, så det är okej att hårdkoda anslutningssträng. För nätverksdatabaser som PostgreSQL och SQL Server bör du alltid lagra dina anslutningssträng 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 ska 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. I terminalen som är begränsad till projektmappen ContosoPizza kör du följande kommando för att generera en migrering för att skapa databastabellerna:

    dotnet ef migrations add InitialCreate --context PizzaContext
    

    I kommandot ovan:

    • Migreringen heter: 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å det här kommandot skapar migreringen i projektkatalogen.

    Dricks

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

Inspektera databasen

EF Core har skapat en databas för din app. Nu ska vi ta en titt i databasen med hjälp av SQLite-tillägget.

  1. Högerklicka på filen ContosoPizza.db i Utforskaren och välj Öppna databas.

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

    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 har skapats.
    • Tabellnamn hämtades från namnen DbSet på egenskaperna på PizzaContext.
    • Egenskaper med namnet Id härleddes som autoincrementing 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å entitetsklasserna.

    Kommentar

    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. EF Core härleder till exempel en egenskap med namnet Id eller <entity name>Id som den genererade tabellens primära nyckel. Om du väljer att inte använda namngivningskonventionen måste du kommentera egenskapen med [Key] attributet eller konfigurera den 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 för 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.

    Den uppdaterade Pizza.cs filen bör se ut som följande kod:

    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.

    Den uppdaterade Sauce.cs filen bör se ut som följande kod:

    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 egenskapen Name .

    5. Lägg till en Pizzas egenskap av typen ICollection<Pizza>?. Den här ändringen gör Pizza-Topping en många-till-många-relation.

    6. Lägg till ett [JsonIgnore] attribut i egenskapen Pizzas .

      Viktigt!

      Det här attributet förhindrar att entiteter Topping 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 topping. 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.

    Den uppdaterade Topping.cs-filen bör se ut som följande kod:

    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
    

    Det här kommandot skapar en migrering med namnet: ModelRevisions.

    Kommentar

    Du ser det här meddelandet: En åtgärd har skapats som kan leda till dataförlust. Granska migreringen för noggrannhet. Det här meddelandet visades eftersom du ändrade 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 migreringen inte tar bort eller trunkerar några data.

  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.

    Dricks

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

  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.

Kommentar

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

Du använde migreringar för att definiera och uppdatera ett databasschema. I nästa lektion slutför du metoderna i PizzaService som manipulerar data.

Kontrollera dina kunskaper

1.

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