Delen via


Pas migraties van Entity Framework Core toe in .NET Aspire

Aangezien .NET.NET Aspire projecten een containerarchitectuur gebruiken, zijn databases kortstondig en kunnen ze op elk gewenst moment opnieuw worden gemaakt. Entity Framework Core (EF Core) maakt gebruik van een functie met de naam migraties voor het maken en bijwerken van databaseschema's. Omdat databases opnieuw worden gemaakt wanneer de app wordt gestart, moet u migraties toepassen om het databaseschema te initialiseren telkens wanneer uw app wordt gestart. Dit wordt bereikt door een migratieserviceproject te registreren in uw app die migraties uitvoert tijdens het opstarten.

In deze zelfstudie leert u hoe u .NET Aspire projecten configureert om EF Core migraties uit te voeren tijdens het opstarten van de app.

Voorwaarden

Als u met .NET.NET Aspirewilt werken, hebt u het volgende lokaal geïnstalleerd:

Zie .NET.NET Aspire setup en hulpprogramma'sen .NET.NET Aspire SDK-voor meer informatie.

De starter-app verkrijgen

In deze handleiding wordt een voorbeeldapp gebruikt om te laten zien hoe u EF Core-migraties in .NET Aspirekunt toepassen. Gebruik Visual Studio om de voorbeeld-app te klonen vanuit GitHub of gebruik de volgende opdracht:

git clone https://github.com/MicrosoftDocs/aspire-docs-samples/

De voorbeeld-app bevindt zich in de map SupportTicketApi. Open de oplossing in Visual Studio of VS Code en neem even de tijd om de voorbeeld-app te controleren en ervoor te zorgen dat deze wordt uitgevoerd voordat u doorgaat. De voorbeeld-app is een elementaire ondersteuningsticket-API en bevat de volgende projecten:

  • SupportTicketApi.Api: het ASP.NET Core project dat als host fungeert voor de API.
  • SupportTicketApi.AppHost: bevat de .NET.NET Aspire app-host en -configuratie.
  • SupportTicketApi.Data: bevat de EF Core contexten en modellen.
  • SupportTicketApi.ServiceDefaults: bevat de standaardserviceconfiguraties.

Voer de app uit om ervoor te zorgen dat deze werkt zoals verwacht. Wacht totdat alle resources in het .NET.NET Aspire dashboard draaien en in orde zijn. Selecteer vervolgens het https Swagger-eindpunt en test het GET /api/SupportTickets-eindpunt van de API door de bewerking uit te vouwen en uit te proberen. Selecteer uitvoeren om de aanvraag te verzenden en het antwoord weer te geven:

[
  {
    "id": 1,
    "title": "Initial Ticket",
    "description": "Test ticket, please ignore."
  }
]

Sluit de browsertabbladen met het Swagger-eindpunt en het .NET.NET Aspire-dashboard en stop de foutopsporing.

Migraties maken

Begin met het maken van enkele migraties die u wilt toepassen.

  1. Een terminal openen (Ctrl-+` in Visual Studio).

  2. Stel SupportTicketApi\SupportTicketApi.Api in als de huidige map.

  3. Gebruik het dotnet ef opdrachtregelprogramma om een nieuwe migratie te maken om de initiële status van het databaseschema vast te leggen:

    dotnet ef migrations add InitialCreate --project ..\SupportTicketApi.Data\SupportTicketApi.Data.csproj
    

    De volgende opdracht:

    • Voert migratie-opdrachtregelprogramma EF Core uit in de map SupportTicketApi.Api. dotnet ef wordt uitgevoerd op deze locatie omdat de API-service de db-context gebruikt.
    • Hiermee maakt u een migratie met de naam InitialCreate.
    • Hiermee maakt u de migratie in de map Migrations in het project SupportTicketApi.Data.
  4. Wijzig het model zodat het een nieuwe eigenschap bevat. Open SupportTicketApi.Data\Models\SupportTicket.cs en voeg een nieuwe eigenschap toe aan de klasse SupportTicket:

    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; }
    }
    
  5. Maak nog een nieuwe migratie om de wijzigingen in het model vast te leggen:

    dotnet ef migrations add AddCompleted --project ..\SupportTicketApi.Data\SupportTicketApi.Data.csproj
    

Nu moet u enkele migraties toepassen. Vervolgens maakt u een migratieservice die deze migraties toepast tijdens het opstarten van de app.

De migratieservice maken

Als u de migraties bij het opstarten wilt uitvoeren, moet u een service maken die de migraties toepast.

  1. Voeg een nieuw Worker Service project toe aan de oplossing. Als u Visual Studiogebruikt, klikt u met de rechtermuisknop op de oplossing in Solution Explorer en selecteert u Add>New Project. Selecteer Worker Service, geef het project de naam SupportTicketApi.MigrationService en het doel .NET 8,0. Als u de opdrachtregel gebruikt, voert u de volgende opdrachten uit vanuit de oplossingsmap:

    dotnet new worker -n SupportTicketApi.MigrationService -f "net8.0"
    dotnet sln add SupportTicketApi.MigrationService
    
  2. Voeg de SupportTicketApi.Data en SupportTicketApi.ServiceDefaults projectverwijzingen toe aan het SupportTicketApi.MigrationService project met behulp van Visual Studio of de opdrachtregel:

    dotnet add SupportTicketApi.MigrationService reference SupportTicketApi.Data
    dotnet add SupportTicketApi.MigrationService reference SupportTicketApi.ServiceDefaults
    
  3. Voeg de 📦Aspiretoe. Microsoft.EntityFrameworkCore.SqlServer NuGet-pakketreferentie naar het SupportTicketApi.MigrationService project met behulp van Visual Studio of de opdrachtregel:

    cd SupportTicketApi.MigrationService
    dotnet add package Aspire.Microsoft.EntityFrameworkCore.SqlServer -v "9.1.0"
    
  4. Voeg de gemarkeerde regels toe aan het Program.cs-bestand in het SupportTicketApi.MigrationService project:

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

    In de voorgaande code:

  5. Vervang de inhoud van het Worker.cs-bestand in het SupportTicketApi.MigrationService project door de volgende 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);
            });
        }
    }
    

    In de voorgaande code:

    • De methode ExecuteAsync wordt aangeroepen wanneer de werknemer begint. Op zijn beurt worden de volgende stappen uitgevoerd:
      1. Hiermee haalt u een referentie op naar de TicketContext-service van deze serviceprovider.
      2. Roept RunMigrationAsync aan om alle openstaande migraties toe te passen.
      3. Roept SeedDataAsync aan om de database te seeden met initiële gegevens.
      4. Stopt de werknemer met StopApplication.
    • De methoden RunMigrationAsync en SeedDataAsync bevatten beide hun respectieve databasebewerkingen met behulp van uitvoeringsstrategieën voor het afhandelen van tijdelijke fouten die kunnen optreden bij interactie met de database. Zie Verbindingstolerantievoor meer informatie over uitvoeringsstrategieën.

De migratieservice toevoegen aan de orchestrator

De migratieservice wordt gemaakt, maar moet worden toegevoegd aan de .NET.NET Aspire app-host, zodat deze wordt uitgevoerd wanneer de app wordt gestart.

  1. Open in het SupportTicketApi.AppHost project het bestand Program.cs.

  2. Voeg de volgende gemarkeerde code toe aan de methode ConfigureServices:

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

    Hiermee wordt het SupportTicketApi.MigrationService project als een service in de .NET.NET Aspire app-host opgenomen.

  3. Als de code het migratieserviceproject niet kan oplossen, voegt u een verwijzing toe naar het migratieserviceproject in het AppHost-project:

    dotnet add SupportTicketApi.AppHost reference SupportTicketApi.MigrationService
    

    Belangrijk

    Als u Visual Studiogebruikt en u de optie Enlist in Aspire orchestration hebt geselecteerd bij het maken van het Worker Service project, wordt soortgelijke code automatisch toegevoegd met de servicenaam supportticketapi-migrationservice. Vervang die code door de voorgaande code.

Bestaande seeding-code verwijderen

Aangezien de migratieservice de database zaait, moet u de bestaande gegevenszaaicode uit het API-project verwijderen.

  1. Open in het SupportTicketApi.Api project het bestand Program.cs.

  2. Verwijder de gemarkeerde regels.

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

De migratieservice testen

Nu de migratieservice is geconfigureerd, voert u de app uit om de migraties te testen.

  1. Voer de app uit en bekijk het SupportTicketApi dashboard.

  2. Na een korte wachttijd wordt de status van de migrations-service weergegeven Voltooid.

    Een schermopname van het .NET.NET Aspire-dashboard met de migratieservice met de status Voltooid.

  3. Selecteer het pictogram Console logs in de migratieservice om de logboeken te onderzoeken met de SQL-opdrachten die zijn uitgevoerd.

De code ophalen

U vindt de voltooide voorbeeld-app op GitHub.

Meer voorbeeldcode

De Aspire Shop voorbeeld-app gebruikt deze benadering om migraties toe te passen. Zie het AspireShop.CatalogDbManager project voor de implementatie van de migratieservice.