Wenden Sie Entity Framework Core-Migrationen in .NET Aspire an
Da .NET.NET Aspire Projekte eine containerisierte Architektur verwenden, sind Datenbanken kurzlebig und können jederzeit neu erstellt werden. Entity Framework Core (EF Core) verwendet ein Feature namens Migrationen zum Erstellen und Aktualisieren von Datenbankschemas. Da Datenbanken beim Starten der App neu erstellt werden, müssen Sie Migrationen anwenden, um das Datenbankschema bei jedem Start der App zu initialisieren. Dies erfolgt durch Registrieren eines Migrationsdienstprojekts in Ihrer App, das Migrationen während des Starts ausführt.
In diesem Lernprogramm erfahren Sie, wie Sie .NET Aspire Projekte so konfigurieren, dass EF Core Migrationen während des App-Starts ausgeführt werden.
Voraussetzungen
Um mit .NET.NET Aspirezu arbeiten, benötigen Sie folgendes lokal installiert:
- .NET 8.0 oder .NET 9,0
- Eine OCI-kompatible Containerlaufzeit, z. B.:
- Docker Desktop oder Podman. Weitere Informationen finden Sie unter container runtime.
- Eine integrierte Entwicklerumgebung (Integrated Developer Environment, IDE) oder ein Code-Editor, z. B.:
- Visual Studio 2022 Version 17.9 oder höher (optional)
-
Visual Studio Code (optional)
- C# Dev Kit: Erweiterung (Optional)
- JetBrains Rider mit .NET.NET Aspire Plug-in (Optional)
Weitere Informationen finden Sie unter .NET.NET Aspire Setup und Toolsund .NET.NET Aspire SDK.
Startanwendung herunterladen
In diesem Lernprogramm wird eine Beispiel-App verwendet, die veranschaulicht, wie EF Core Migrationen in .NET Aspireangewendet werden. Verwenden Sie Visual Studio, um die Beispiel-App von GitHub zu klonen oder den folgenden Befehl zu verwenden:
git clone https://github.com/MicrosoftDocs/aspire-docs-samples/
Die Beispiel-App befindet sich im Ordner SupportTicketApi. Öffnen Sie die Lösung in Visual Studio oder VS Code, und nehmen Sie sich einen Moment Zeit, um die Beispiel-App zu überprüfen und sicherzustellen, dass sie ausgeführt wird, bevor Sie fortfahren. Die Beispiel-App ist eine rudimentäre Support-Ticket-API, und enthält die folgenden Projekte:
- SupportTicketApi.Api: Das ASP.NET Core Projekt, das die API hostet.
- SupportTicketApi.AppHost: Enthält den .NET.NET Aspire App-Host und die Konfiguration.
- SupportTicketApi.Data: Enthält die EF Core Kontexte und Modelle.
- SupportTicketApi.ServiceDefaults: Enthält die Standarddienstkonfigurationen.
Führen Sie die App aus, um sicherzustellen, dass sie erwartungsgemäß funktioniert. Warten Sie im .NET.NET Aspire-Dashboard, bis alle Ressourcen aktiv und fehlerfrei sind. Wählen Sie dann den https Swagger-Endpunkt aus, und testen Sie den API-Endpunkt GET /api/SupportTickets, indem Sie die Operation erweitern und Ausprobierenauswählen. Wählen Sie Ausführen aus, um die Anforderung zu senden und um die Antwort anzuzeigen.
[
{
"id": 1,
"title": "Initial Ticket",
"description": "Test ticket, please ignore."
}
]
Schließen Sie die Browserregisterkarten, die den Swagger-Endpunkt und das Dashboard .NET.NET Aspire anzeigen, und beenden Sie dann das Debuggen.
Migrationen erstellen
Beginnen Sie, indem Sie einige Migrationen erstellen, die angewendet werden sollen.
Öffnen Sie ein Terminal (STRG+` in Visual Studio).
Legen Sie SupportTicketApi\SupportTicketApi.Api als aktuelles Verzeichnis fest.
Verwenden Sie das
dotnet ef
Befehlszeilentool, um eine neue Migration zu erstellen, um den Anfangszustand des Datenbankschemas zu erfassen:dotnet ef migrations add InitialCreate --project ..\SupportTicketApi.Data\SupportTicketApi.Data.csproj
Der Befehl "Fortfahren":
- Führt das Befehlszeilentool für die Migration EF Core im Verzeichnis SupportTicketApi.Api aus.
dotnet ef
wird an diesem Ort ausgeführt, da der API-Dienst den DB-Kontext verwendet. - Erstellt eine Migration mit dem Namen InitialCreate.
- Erstellt die Migration im Migrations- Ordner des Projekts SupportTicketApi.Data.
- Führt das Befehlszeilentool für die Migration EF Core im Verzeichnis SupportTicketApi.Api aus.
Ändern Sie das Modell so, dass es eine neue Eigenschaft enthält. Öffnen Sie SupportTicketApi.Data\Models\SupportTicket.cs, und fügen Sie der klasse
SupportTicket
eine neue Eigenschaft hinzu:public sealed class SupportTicket { public int Id { get; set; } [Required] public string Title { get; set; } = string.Empty; [Required] public string Description { get; set; } = string.Empty; public bool Completed { get; set; } }
Erstellen Sie eine weitere neue Migration, um die Änderungen am Modell zu erfassen:
dotnet ef migrations add AddCompleted --project ..\SupportTicketApi.Data\SupportTicketApi.Data.csproj
Jetzt müssen Sie einige Migrationen durchführen. Als Nächstes erstellen Sie einen Migrationsdienst, der diese Migrationen während des App-Starts anwendet.
Erstellen Sie den Migrationsdienst
Um die Migrationen beim Start auszuführen, müssen Sie einen Dienst erstellen, der die Migrationen anwendet.
Fügen Sie der Projektmappe ein neues Worker Service-Projekt hinzu. Wenn Sie Visual Studioverwenden, klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Projektmappe, und wählen Sie Add>New Projectaus. Wählen Sie Worker Serviceaus, benennen Sie das Projekt SupportTicketApi.MigrationService und setzen Sie das Ziel auf .NET 8.0. Wenn Sie die Befehlszeile verwenden, verwenden Sie die folgenden Befehle aus dem Lösungsverzeichnis:
dotnet new worker -n SupportTicketApi.MigrationService -f "net8.0" dotnet sln add SupportTicketApi.MigrationService
Fügen Sie zum SupportTicketApi.Data-Projekt die SupportTicketApi.ServiceDefaults- und SupportTicketApi.MigrationService-Projektverweise mithilfe von Visual Studio oder der Befehlszeile hinzu.
dotnet add SupportTicketApi.MigrationService reference SupportTicketApi.Data dotnet add SupportTicketApi.MigrationService reference SupportTicketApi.ServiceDefaults
Fügen Sie die 📦Aspire.Microsoft.EntityFrameworkCore.SqlServer NuGet-Paketreferenz zum Projekt SupportTicketApi.MigrationService mithilfe von Visual Studio oder über die Befehlszeile hinzu.
cd SupportTicketApi.MigrationService dotnet add package Aspire.Microsoft.EntityFrameworkCore.SqlServer -v "9.1.0"
Fügen Sie der Program.cs-Datei im SupportTicketApi.MigrationService Projekt die hervorgehobenen Zeilen hinzu:
using SupportTicketApi.Data.Contexts; using SupportTicketApi.MigrationService; var builder = Host.CreateApplicationBuilder(args); builder.AddServiceDefaults(); builder.Services.AddHostedService<Worker>(); builder.Services.AddOpenTelemetry() .WithTracing(tracing => tracing.AddSource(Worker.ActivitySourceName)); builder.AddSqlServerDbContext<TicketContext>("sqldata"); var host = builder.Build(); host.Run();
Im vorherigen Code:
- Die Erweiterungsmethode
fügt die Standardfunktionalität für Dienste hinzu. - Die
AddOpenTelemetry
Erweiterungsmethode konfiguriert OpenTelemetry Funktionalität. - Die
AddSqlServerDbContext
-Erweiterungsmethode fügt der Dienstkollektion denTicketContext
-Dienst hinzu. Dieser Dienst wird zum Ausführen von Migrationen und zum Seeden der Datenbank verwendet.
- Die Erweiterungsmethode
Ersetzen Sie den Inhalt der datei Worker.cs im SupportTicketApi.MigrationService Projekt durch den folgenden Code:
using System.Diagnostics; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage; using OpenTelemetry.Trace; using SupportTicketApi.Data.Contexts; using SupportTicketApi.Data.Models; namespace SupportTicketApi.MigrationService; public class Worker( IServiceProvider serviceProvider, IHostApplicationLifetime hostApplicationLifetime) : BackgroundService { public const string ActivitySourceName = "Migrations"; private static readonly ActivitySource s_activitySource = new(ActivitySourceName); protected override async Task ExecuteAsync(CancellationToken cancellationToken) { using var activity = s_activitySource.StartActivity("Migrating database", ActivityKind.Client); try { using var scope = serviceProvider.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService<TicketContext>(); await RunMigrationAsync(dbContext, cancellationToken); await SeedDataAsync(dbContext, cancellationToken); } catch (Exception ex) { activity?.RecordException(ex); throw; } hostApplicationLifetime.StopApplication(); } private static async Task RunMigrationAsync(TicketContext dbContext, CancellationToken cancellationToken) { var strategy = dbContext.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async () => { // Run migration in a transaction to avoid partial migration if it fails. await dbContext.Database.MigrateAsync(cancellationToken); }); } private static async Task SeedDataAsync(TicketContext dbContext, CancellationToken cancellationToken) { SupportTicket firstTicket = new() { Title = "Test Ticket", Description = "Default ticket, please ignore!", Completed = true }; var strategy = dbContext.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async () => { // Seed the database await using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken); await dbContext.Tickets.AddAsync(firstTicket, cancellationToken); await dbContext.SaveChangesAsync(cancellationToken); await transaction.CommitAsync(cancellationToken); }); } }
Im vorherigen Code:
- Die
ExecuteAsync
-Methode wird aufgerufen, wenn der Worker startet. Sie führt wiederum die folgenden Schritte aus:- Ruft eine Referenz auf den Dienst
TicketContext
vom Dienstanbieter ab. - Ruft
RunMigrationAsync
auf, um ausstehende Migrationen anzuwenden. - Ruft
SeedDataAsync
auf, um die Datenbank mit Anfangsdaten zu versehen. - Beendet den Arbeiter mit
StopApplication
.
- Ruft eine Referenz auf den Dienst
- Die methoden
RunMigrationAsync
undSeedDataAsync
kapseln ihre jeweiligen Datenbankvorgänge mithilfe von Ausführungsstrategien, um vorübergehende Fehler zu behandeln, die bei der Interaktion mit der Datenbank auftreten können. Weitere Informationen zu Durchführungsstrategien finden Sie unter Verbindungszuverlässigkeit.
- Die
Fügen Sie den Migrationsdienst dem Orchestrator hinzu
Der Migrationsdienst wird erstellt, muss jedoch dem .NET.NET Aspire App-Host hinzugefügt werden, damit er beim Starten der App ausgeführt wird.
Öffnen Sie im SupportTicketApi.AppHost Projekt die Program.cs Datei.
Fügen Sie der
ConfigureServices
-Methode den folgenden hervorgehobenen Code hinzu:var builder = DistributedApplication.CreateBuilder(args); var sql = builder.AddSqlServer("sql", port: 14329) .WithEndpoint(name: "sqlEndpoint", targetPort: 14330) .AddDatabase("sqldata"); builder.AddProject<Projects.SupportTicketApi_Api>("api") .WithReference(sql) .WaitFor(sql); builder.AddProject<Projects.SupportTicketApi_MigrationService>("migrations") .WithReference(sql) .WaitFor(sql); builder.Build().Run();
Dadurch wird das SupportTicketApi.MigrationService-Projekt als Dienst im .NET.NET Aspire App-Host aufgelistet.
Wenn der Code das Migrationsdienstprojekt nicht auflösen kann, fügen Sie einen Verweis auf das Migrationsdienstprojekt im AppHost-Projekt hinzu:
dotnet add SupportTicketApi.AppHost reference SupportTicketApi.MigrationService
Wichtig
Wenn Sie Visual Studioverwenden und beim Erstellen des Projekts Enlist in Aspire orchestration die Option Worker Service ausgewählt haben, wird automatisch ähnlicher Code mit dem Dienstnamen
supportticketapi-migrationservice
hinzugefügt. Ersetzen Sie diesen Code durch den vorherigen Code.
Vorhandenen Seedingcode entfernen
Da der Migrationsdienst die Datenbank besät, sollten Sie den vorhandenen Datensatzungscode aus dem API-Projekt entfernen.
Öffnen Sie im SupportTicketApi.Api Projekt die Program.cs Datei.
Löschen Sie die hervorgehobenen Zeilen.
if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); using (var scope = app.Services.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService<TicketContext>(); context.Database.EnsureCreated(); if(!context.Tickets.Any()) { context.Tickets.Add(new SupportTicket { Title = "Initial Ticket", Description = "Test ticket, please ignore." }); context.SaveChanges(); } } }
Test des Migrationsdiensts
Nachdem der Migrationsdienst konfiguriert ist, führen Sie die App aus, um die Migrationen zu testen.
Führen Sie die App aus, und beobachten Sie das SupportTicketApi-Dashboard.
Nach einer kurzen Wartezeit wird der
migrations
Dienststatus Abgeschlossenangezeigt.Wählen Sie das Symbol "Console logs" im Migrationsdienst aus, um die Protokolle zu untersuchen, in denen die sql-Befehle angezeigt werden, die ausgeführt wurden.
Code abrufen
Sie finden die abgeschlossene Beispiel-App auf GitHub.
Weitere Beispielcode
Die Aspire Shop Beispiel-App verwendet diesen Ansatz, um Migrationen anzuwenden. Informationen zur Implementierung des Migrationsdiensts finden Sie im AspireShop.CatalogDbManager
Projekt.