Övning – Konfigurera en migrering
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.
Ö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
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.NotImplementedException
för närvarande . - I Program.cs
PizzaService
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 iPizzaController
konstruktorn. - Mappen Modeller innehåller de modeller som
PizzaService
ochPizzaController
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:
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.
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:
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.
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.
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öradotnet 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.
Högerklicka på katalogen ContosoPizza och lägg till en ny mapp med namnet Data.
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 sammaDbContext
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
exponerasPizzas
egenskaperna ,Toppings
ochSauces
. Ändringar som du gör i de samlingar som dessa egenskaper exponerar sprids till databasen.
- Konstruktorn accepterar en parameter av typen
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.
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.
Spara alla ändringar. GitHub Codespaces sparar ändringarna automatiskt.
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.
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ånDbContext
.
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).
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ändaAdd-Migration
powershell-cmdletarna ochUpdate-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.
Högerklicka på filen ContosoPizza.db i Utforskaren och välj Öppna databas.
En SQLite Explorer-mapp visas i explorer-fönstret.
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.
- 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>
respektiveFK_<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 iOnModelCreating
metoden förDbContext
.
Ä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).
I Models\Pizza.cs gör du följande ändringar:
- Lägg till ett
using
direktiv förSystem.ComponentModel.DataAnnotations
. - Lägg till ett
[Required]
attribut föreName
egenskapen för att markera egenskapen efter behov. - Lägg till ett
[MaxLength(100)]
attribut föreName
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; } }
- Lägg till ett
I Models\Sauce.cs gör du följande ändringar:
- Lägg till ett
using
direktiv förSystem.ComponentModel.DataAnnotations
. - Lägg till ett
[Required]
attribut föreName
egenskapen för att markera egenskapen efter behov. - Lägg till ett
[MaxLength(100)]
attribut föreName
egenskapen för att ange en maximal stränglängd på 100. - Lägg till en
bool
egenskap med namnetIsVegan
.
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; } }
- Lägg till ett
I Models\Topping.cs gör du följande ändringar:
Lägg till
using
direktiv förSystem.ComponentModel.DataAnnotations
ochSystem.Text.Json.Serialization
.Lägg till ett
[Required]
attribut föreName
egenskapen för att markera egenskapen efter behov.Lägg till ett
[MaxLength(100)]
attribut föreName
egenskapen för att ange en maximal stränglängd på 100.Lägg till en
decimal
egenskap med namnetCalories
direkt efter egenskapenName
.Lägg till en
Pizzas
egenskap av typenICollection<Pizza>?
. Den här ändringen görPizza
-Topping
en många-till-många-relation.Lägg till ett
[JsonIgnore]
attribut i egenskapenPizzas
.Viktigt!
Det här attributet förhindrar att entiteter
Topping
inkluderarPizzas
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; } }
Spara alla ändringar och kör
dotnet build
.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
tillTopping
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.Tillämpa ModelRevisions-migreringen genom att köra följande kommando:
dotnet ef database update --context PizzaContext
I namnlisten i mappen SQLite Explorer väljer du knappen Uppdatera databaser .
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 ochSauces
.Calories
definieras som entext
kolumn eftersom SQLite inte har någon matchandedecimal
typ.IsVegan
På samma sätt definieras som eninteger
kolumn. SQLite definierarbool
ingen typ.- I båda fallen hanterar EF Core översättningen.
- Kolumnen
Name
i varje tabell har markeratsnot null
, men SQLite harMaxLength
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
MaxLength
gör andra databaser som SQL Server och PostgreSQL det.- En
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.