Übung: Einrichten einer Migration
In dieser Lerneinheit erstellen Sie C#-Entitätsklassen, die Tabellen in einer lokalen SQLite-Datenbank zugeordnet werden. Das EF Core-Migrationsfeature erstellt Tabellen aus diesen Entitäten.
Eine Migration bietet eine Möglichkeit, das Datenbankschema inkrementell zu aktualisieren.
Abrufen der Projektdateien
Rufen Sie zunächst die Projektdateien ab. Es gibt verschiedene Möglichkeiten, die Projektdateien abzurufen:
- Verwenden von GitHub Codespaces
- Klonen des GitHub-Repositorys
Wenn Sie eine kompatible Containerruntime installiert haben, können Sie auch die Dev Containers-Erweiterung verwenden, um das Repository in einem Container mit vorinstallierten Tools zu öffnen.
Verwenden von GitHub Codespaces
Ein Codespace ist eine in der Cloud gehostete IDE. Wenn Sie GitHub Codespaces verwenden, wechseln Sie zum Repository in Ihrem Browser. Wählen Sie Code aus, und erstellen Sie dann einen neuen Codespace im main
-Branch.
Klonen des GitHub-Repositorys
Wenn Sie GitHub Codespaces nicht verwenden, können Sie das GitHub-Projektrepository klonen und die Dateien dann als Ordner in Visual Studio Code öffnen.
Öffnen Sie ein Befehlsterminal, und klonen Sie dann das Projekt aus GitHub mithilfe der Eingabeaufforderung:
git clone https://github.com/MicrosoftDocs/mslearn-persist-data-ef-core
Wechseln Sie zum Ordner mslearn-persist-data-ef-core, und öffnen Sie dann das Projekt in Visual Studio Code:
cd mslearn-persist-data-ef-core code .
Überprüfen des Codes
Nachdem Sie nun über die Projektdateien verfügen, mit denen Sie arbeiten können, sehen wir uns an, was im Projekt enthalten ist, und überprüfen den Code.
- Das ASP.NET Core-Web-API-Projekt, die sich im Verzeichnis ContosoPizza befindet. Die Dateipfade, auf die wir in diesem Modul verweisen, sind relativ zum ContosoPizza-Verzeichnis.
- Services/PizzaService.cs ist eine Dienstklasse, die CRUD-Methoden definiert. Alle Methoden lösen zurzeit eine
System.NotImplementedException
aus. - In Program.cs ist
PizzaService
über das Abhängigkeitsinjektionssystem von ASP.NET Core registriert. - Controllers/PizzaController.cs ist ein Wert für
ApiController
, der einen Endpunkt für die HTTP-Verben „POST“, „GET“, „PUT“ und „DELETE“ verfügbar macht. Diese Verben rufen die entsprechenden CRUD-Methoden fürPizzaService
auf.PizzaService
wird in den KonstruktorPizzaController
eingefügt. - Der Ordner Modelle enthält die Modelle, die von
PizzaService
undPizzaController
verwendet werden. - Die Entitätsmodelle Pizza.cs, Topping.cs und Sauce.cs weisen die folgenden Beziehungen auf:
- Eine Pizza kann mit einer oder mehreren Zutaten belegt sein.
- Ein Belag kann auf einer oder mehreren Pizzas verwendet werden.
- Eine Pizza kann nur eine Soße aufweisen, aber eine Soße kann auf vielen Pizzas verwendet werden.
Erstellen der App
Gehen Sie wie folgt vor, um die App in Visual Studio Code zu erstellen:
Klicken Sie im Bereich Explorer mit der rechten Maustaste auf das Verzeichnis ContosoPizza, und wählen Sie In integriertem Terminal öffnen aus.
Dadurch wird ein Terminalbereich für das Verzeichnis ContosoPizza geöffnet.
Verwenden Sie den folgenden Befehl, um die App zu erstellen:
dotnet build
Der Code sollte ohne Warnungen oder Fehler erstellt werden.
Hinzufügen von NuGet-Paketen und EF Core-Tools
Die Datenbank-Engine, mit der Sie in diesem Modul arbeiten, ist SQLite. SQLite ist eine schlanke, dateibasierte Datenbank-Engine. Sie eignet sich gut für Entwicklung und Tests, aber auch für kleine Produktionsbereitstellungen.
Hinweis
Wie bereits erwähnt, können Datenbankanbieter in EF Core ergänzt werden. SQLite ist eine gute Wahl für dieses Modul, da es schlank und plattformübergreifend ist. Sie können denselben Code verwenden, um verschiedene andere Datenbank-Engines wie SQL Server und PostgreSQL zu verwenden. Sie können sogar mehrere Datenbank-Engines in derselben App verwenden.
Bevor Sie beginnen, fügen Sie die erforderlichen Pakete hinzu:
Führen Sie im Terminalbereich den folgenden Befehl aus:
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
Dieser Befehl fügt das NuGet-Paket hinzu, das den EF Core-SQLite-Datenbankanbieter und alle zugehörigen Abhängigkeiten enthält, einschließlich der allgemeinen EF Core-Dienste.
Führen Sie als Nächstes diesen Befehl aus:
dotnet add package Microsoft.EntityFrameworkCore.Design
Dieser Befehl fügt Pakete hinzu, die für die EF Core-Tools erforderlich sind.
Führen Sie zum Abschluss den folgenden Befehl aus:
dotnet tool install --global dotnet-ef
Dieser Befehl installiert
dotnet ef
, das Tool, mit dem Sie Migrationen und Gerüstbau erstellen.Tipp
Wenn
dotnet ef
bereits installiert ist, können Sie dieses Tool aktualisieren, indem Siedotnet tool update --global dotnet-ef
ausführen.
Modellgerüste und DbContext
Jetzt fügen Sie eine DbContext
-Implementierung hinzu und konfigurieren diese. DbContext
ist ein Gateway, über das Sie mit der Datenbank interagieren können.
Klicken Sie mit der rechten Maustaste auf das Verzeichnis ContosoPizza, und fügen Sie einen neuen Ordner namens Data hinzu.
Erstellen Sie im Ordner Data eine neue Datei namens PizzaContext.cs. Fügen Sie der leeren Datei den folgenden Code hinzu:
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>(); }
Für den Code oben gilt:
- Der Konstruktor akzeptiert einen Parameter vom Typ
DbContextOptions<PizzaContext>
. Durch den Konstruktor kann externer Code an die Konfiguration übergeben werden, sodass dasselbeDbContext
-Element von Test- und Produktionscode gemeinsam genutzt und sogar mit verschiedenen Anbietern verwendet werden kann. - Die
DbSet<T>
-Eigenschaften entsprechen Tabellen, die in der Datenbank erstellt werden sollen. - Die Tabellennamen stimmen mit den Eigenschaftsnamen „
DbSet<T>
“ in der Klasse „PizzaContext
“ überein. Sie können dieses Verhalten bei Bedarf außer Kraft setzen. - Bei der Instanziierung macht
PizzaContext
die Eigenschaften „Pizzas
“, „Toppings
“ und „Sauces
“ verfügbar. Änderungen, die Sie an den Auflistungen vornehmen, die diese Eigenschaften verfügbar machen, werden an die Datenbank weitergegeben.
- Der Konstruktor akzeptiert einen Parameter vom Typ
Ersetzen Sie
// Add the PizzaContext
in der Datei Program.cs durch den folgenden Code:builder.Services.AddSqlite<PizzaContext>("Data Source=ContosoPizza.db");
Der obige Code:
PizzaContext
wird mit dem ASP.NET Core-Abhängigkeitsinjektionssystem registriert.- Gibt an, dass
PizzaContext
den SQLite-Datenbankanbieter verwendet. - Definiert eine SQLite-Verbindungszeichenfolge, die auf die lokale Datei ContosoPizza.db verweist.
Hinweis
Da SQLite lokale Datenbankdateien verwendet, stellt die Hartcodierung der Verbindungszeichenfolge kein Problem dar. Für Netzwerkdatenbanken wie PostgreSQL und SQL Server sollten Sie Ihre Verbindungszeichenfolgen grundsätzlich sicher speichern. Verwenden Sie für die lokale Entwicklung den Secret Manager. Bei Produktionsbereitstellungen sollten Sie einen Dienst wie Azure Key Vault in Betracht ziehen.
Ersetzen Sie zudem
// Additional using declarations
in der Datei Program.cs durch den folgenden Code.using ContosoPizza.Data;
Dieser Code löst Abhängigkeiten aus dem vorherigen Schritt auf.
Speichern Sie alle Änderungen. GitHub Codespaces speichert Ihre Änderungen automatisch.
Erstellen Sie die App im Terminal, indem Sie
dotnet build
ausführen. Der Buildvorgang sollte erfolgreich und ohne Warnungen oder Fehler abgeschlossen werden.
Erstellen und Ausführen einer Migration
Als Nächstes erstellen Sie eine Migration, mit der Sie Ihre anfängliche Datenbank erstellen können.
Führen Sie im dem Gültigkeitsbereich des ContosoPizza-Projektordners zugeordneten Terminal den folgenden Befehl aus, um eine Migration zum Erstellen der Datenbanktabellen zu generieren:
dotnet ef migrations add InitialCreate --context PizzaContext
Für den obigen Befehl gilt Folgendes:
- Die Migration heißt „InitialCreate“.
- Die Option
--context
gibt den Namen der Klasse im Projekt ContosoPizza an, der vonDbContext
abgeleitet wird.
Im Projektstamm ContosoPizza wird ein neues Verzeichnis Migrations angezeigt. Das Verzeichnis enthält die Datei <timestamp>_InitialCreate.cs, die Datenbankänderungen beschreibt, die in ein Datendefinitionssprache-Änderungsskript (Data Definition Language, DDL) übersetzt werden sollen.
Führen Sie den folgenden Befehl aus, um die Migration InitialCreate anzuwenden:
dotnet ef database update --context PizzaContext
Mit diesem Befehl wird die Migration angewendet. Da ContosoPizza.db nicht vorhanden ist, erstellt dieser Befehl die Migration im Projektverzeichnis.
Tipp
Alle Plattformen unterstützen das
dotnet ef
-Tool. In Visual Studio unter Windows können Sie die PowerShell-CmdletsAdd-Migration
undUpdate-Database
im integrierten Fenster der Paket-Manager-Konsole verwenden.
Untersuchen der Datenbank
EF Core hat eine Datenbank für Ihre App erstellt. Als Nächstes sehen wir uns die Datenbank mithilfe der SQLite-Erweiterung genauer an.
Klicken Sie im Bereich Explorer mit der rechten Maustaste auf die Datei ContosoPizza.db, und wählen Sie Datenbank öffnen aus.
Im Explorer-Bereich wird der Ordner SQLite Explorer angezeigt.
Wählen Sie den Ordner SQLite Explorer aus, um den Knoten und alle untergeordneten Knoten zu erweitern. Klicken Sie mit der rechten Maustaste auf ContosoPizza.db, und wählen Sie Tabelle „sqlite_master“ anzeigen aus, um das vollständige Datenbankschema und die Einschränkungen anzuzeigen, die von der Migration erstellt wurden.
- Es wurden Tabellen erstellt, die den einzelnen Entitäten entsprechen.
- Tabellennamen wurden aus den Namen der
DbSet
-Eigenschaften fürPizzaContext
entnommen. - Eigenschaften namens
Id
wurden als automatisch inkrementierte Primärschlüsselfelder abgeleitet. - Die Namenskonventionen für Primärschlüssel- und Fremdschlüsseleinschränkungen von EF Core sind
PK_<primary key property>
bzw.FK_<dependent entity>_<principal entity>_<foreign key property>
. Die Platzhalter<dependent entity>
und<principal entity>
entsprechen den Namen der Entitätsklasse.
Hinweis
Wie ASP.NET Core MVC verwendet EF Core einen Konvention-vor-Konfiguration-Ansatz. EF Core-Konventionen verkürzen die Entwicklungszeit, indem sie auf die Absicht des Entwicklers schließen. EF Core leitet beispielsweise eine Eigenschaft mit dem Namen
Id
oder<entity name>Id
als Primärschlüssel der generierten Tabelle ab. Wenn Sie die Namenskonvention nicht übernehmen möchten, müssen Sie die Eigenschaft mit dem Attribut[Key]
kommentieren oder als Schlüssel in derOnModelCreating
-Methode vonDbContext
konfigurieren.
Ändern des Modells und Aktualisieren des Datenbankschemas
Ihre Vorgesetzten bei Contoso Pizza nennen Ihnen einige neue Anforderungen, weshalb Sie Ihre Entitätsmodelle ändern müssen. In den folgenden Schritten ändern Sie die Modelle mithilfe von Zuordnungsattributen (manchmal auch als Datenanmerkungen bezeichnet).
Nehmen Sie in Models\Pizza.cs die folgenden Änderungen vor:
- Fügen Sie eine
using
-Anweisung fürSystem.ComponentModel.DataAnnotations
hinzu. - Fügen Sie vor der
Name
-Eigenschaft ein[Required]
-Attribut hinzu, um die Eigenschaft als erforderlich zu markieren. - Fügen Sie vor der
Name
-Eigenschaft ein[MaxLength(100)]
-Attribut hinzu, um eine maximale Zeichenfolgenlänge von 100 anzugeben.
Ihre aktualisierte Pizza.cs-Datei sollte wie der folgende Code aussehen:
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; } }
- Fügen Sie eine
Nehmen Sie in Models\Sauce.cs die folgenden Änderungen vor:
- Fügen Sie eine
using
-Anweisung fürSystem.ComponentModel.DataAnnotations
hinzu. - Fügen Sie vor der
Name
-Eigenschaft ein[Required]
-Attribut hinzu, um die Eigenschaft als erforderlich zu markieren. - Fügen Sie vor der
Name
-Eigenschaft ein[MaxLength(100)]
-Attribut hinzu, um eine maximale Zeichenfolgenlänge von 100 anzugeben. - Fügen Sie eine
bool
-Eigenschaft namensIsVegan
hinzu.
Ihre aktualisierte Sauce.cs-Datei sollte wie der folgende Code aussehen:
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; } }
- Fügen Sie eine
Nehmen Sie in Models\Topping.cs die folgenden Änderungen vor:
Fügen Sie
using
-Anweisungen fürSystem.ComponentModel.DataAnnotations
undSystem.Text.Json.Serialization
hinzu.Fügen Sie vor der
Name
-Eigenschaft ein[Required]
-Attribut hinzu, um die Eigenschaft als erforderlich zu markieren.Fügen Sie vor der
Name
-Eigenschaft ein[MaxLength(100)]
-Attribut hinzu, um eine maximale Zeichenfolgenlänge von 100 anzugeben.Fügen Sie eine
decimal
-Eigenschaft namensCalories
unmittelbar nach derName
-Eigenschaft hinzu.Fügen Sie eine
Pizzas
-Eigenschaft vom Typ „ICollection<Pizza>?
“ hinzu. Diese Änderung macht ausPizza
-Topping
eine m:n-Beziehung.Fügen Sie der
Pizzas
-Eigenschaft ein[JsonIgnore]
-Attribut hinzu.Wichtig
Dieses Attribut verhindert, dass
Topping
-Entitäten die EigenschaftPizzas
einschließen, wenn der Web-API-Code die Antwort in JSON serialisiert. Ohne diese Änderung würde eine serialisierte Sammlung von Belägen eine Sammlung mit jeder Pizza enthalten, die den jeweiligen Belag verwendet. Jede Pizza in dieser Auflistung enthielte wiederum eine Auflistung von Belägen, die jeweils wieder eine Auflistung von Pizzas umfassen würde. Diese Art von Endlosschleife wird als Zirkelbezug bezeichnet und kann nicht serialisiert werden.
Ihre aktualisierte Topping.cs-Datei sollte wie der folgende Code aussehen:
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; } }
Speichern Sie alle Änderungen, und führen Sie
dotnet build
aus.Führen Sie den folgenden Befehl aus, um eine Migration zum Erstellen der Datenbanktabellen zu generieren:
dotnet ef migrations add ModelRevisions --context PizzaContext
Mit diesem Befehl wird eine Migration namens „ModelRevisions“ erstellt.
Hinweis
Ihnen wird diese Meldung angezeigt: An operation was scaffolded that may result in the loss of data. Please review the migration for accuracy. (Ein Vorgang wurde erstellt, der zum Datenverlust führen kann. Überprüfen Sie die Migration auf Genauigkeit.) Diese Meldung wurde angezeigt, da Sie die Beziehung von
Pizza
inTopping
von 1:n in m:n geändert haben, was erfordert, dass eine vorhandene Fremdschlüsselspalte gelöscht wird. Da in Ihrer Datenbank noch keine Daten vorhanden sind, ist diese Änderung nicht problematisch. Im Allgemeinen empfiehlt es sich jedoch, die generierte Migration zu überprüfen, wenn diese Warnung angezeigt wird, um sicherzustellen, dass die Migration keine Daten löscht oder abschneidet.Führen Sie den folgenden Befehl aus, um die Migration ModelRevisions anzuwenden:
dotnet ef database update --context PizzaContext
Klicken Sie auf der Titelleiste des Ordners SQLite Explorer auf die Schaltfläche Datenbanken aktualisieren.
Klicken Sie im Ordner SQLite Explorer mit der rechten Maustaste auf ContosoPizza.db. Wählen Sie Tabelle „sqlite_master“ anzeigen aus, um das vollständige Datenbankschema und die Einschränkungen anzuzeigen.
Wichtig
Die SQLite-Erweiterung verwendet geöffnete SQLite-Registerkarten erneut.
- Eine Jointabelle
PizzaTopping
wurde erstellt, um die m:n-Beziehung zwischen Pizzas und Belägen darzustellen. - Neue Felder wurden
Toppings
undSauces
hinzugefügt.Calories
wird alstext
-Spalte definiert, weil SQLite keinen entsprechendendecimal
-Typ aufweist.- In ähnlicher Weise wird
IsVegan
alsinteger
-Spalte definiert. SQLite definiert keinenbool
-Typ. - In beiden Fällen verwaltet EF Core die Übersetzung.
- Die
Name
-Spalte in jeder Tabelle wurde alsnot null
markiert, SQLite weist jedoch keineMaxLength
-Einschränkung auf.
Tipp
EF Core-Datenbankanbieter ordnen den Features einer bestimmten Datenbank ein Modellschema zu. Im Gegensatz zu anderen Datenbanken wie SQL Server und PostgreSQL implementiert SQLite keine entsprechende Einschränkung für
MaxLength
.- Eine Jointabelle
Klicken Sie im Ordner SQLite Explorer mit der rechten Maustaste auf die Tabelle
_EFMigrationsHistory
, und wählen Sie Tabelle anzeigen aus. Die Tabelle enthält eine Liste aller Migrationen, die auf die Datenbank angewendet werden. Da Sie zwei Migrationsvorgänge ausgeführt haben, gibt es zwei Einträge: einen für die InitialCreate-Migration und einen zweiten für ModelRevisions.
Hinweis
In dieser Übung wurden Zuordnungsattribute (Datenanmerkungen) verwendet, um der Datenbank Modelle zuzuordnen. Alternativ zum Zuordnen von Attributen können Sie die Fluent-API „ModelBuilder“ verwenden, um Modelle zu konfigurieren. Beide Ansätze sind möglich, aber einige Entwickler*innen bevorzugen einen der beiden Ansätze.
Sie haben Migrationen verwendet, um ein Datenbankschema zu definieren und zu aktualisieren. In der nächsten Einheit stellen Sie die Methoden zur Datenbearbeitung in PizzaService
fertig.