Terapkan migrasi Entity Framework Core di .NET Aspire
Karena .NET.NET Aspire proyek menggunakan arsitektur kontainer, database bersifat ephemeral dan dapat dibuat ulang kapan saja. Entity Framework Core (EF Core) menggunakan fitur yang disebut migrasi untuk membuat dan memperbarui skema database. Karena database dibuat ulang saat aplikasi dimulai, Anda perlu menerapkan migrasi untuk menginisialisasi skema database setiap kali aplikasi Anda dimulai. Ini dicapai dengan mendaftarkan proyek layanan migrasi di aplikasi Anda yang menjalankan migrasi selama startup.
Dalam tutorial ini, Anda mempelajari cara mengonfigurasi proyek .NET Aspire untuk menjalankan migrasi EF Core selama pengaktifan aplikasi.
Prasyarat
Untuk bekerja dengan .NET.NET Aspire, Anda memerlukan hal berikut yang diinstal secara lokal:
- .NET 8.0 atau .NET 9.0
- Waktu proses kontainer yang sesuai dengan OCI, seperti:
- Docker Desktop atau Podman. Untuk informasi selengkapnya, lihat kontainer runtime.
- Lingkungan Pengembang Terintegrasi (IDE) atau editor kode, seperti:
- Visual Studio 2022 versi 17.9 atau lebih tinggi (Opsional)
-
Visual Studio Code (Opsional)
- C# Dev Kit: Ekstensi (Opsional)
- JetBrains Rider dengan plugin .NET.NET Aspire (Opsional)
Untuk informasi selengkapnya, lihat penyiapan dan alat .NET.NET Aspire, dan .NET.NET Aspire SDK.
Mendapatkan aplikasi awal
Tutorial ini menggunakan aplikasi sampel yang menunjukkan cara menerapkan migrasi EF Core di .NET Aspire. Gunakan Visual Studio untuk mengkloning aplikasi sampel dari GitHub atau gunakan perintah berikut:
git clone https://github.com/MicrosoftDocs/aspire-docs-samples/
Aplikasi sampel berada di folder SupportTicketApi. Buka solusi di Visual Studio atau VS Code dan luangkan waktu sejenak untuk meninjau aplikasi sampel dan pastikan itu berjalan sebelum melanjutkan. Aplikasi sampel adalah API tiket dukungan dasar, dan berisi proyek-proyek berikut:
- SupportTicketApi.Api: Proyek ASP.NET Core yang menjadi host API.
- SupportTicketApi.AppHost: Berisi host dan konfigurasi aplikasi .NET.NET Aspire.
- SupportTicketApi.Data: Berisi konteks dan model EF Core.
- SupportTicketApi.ServiceDefaults: Berisi konfigurasi layanan default.
Jalankan aplikasi untuk memastikan aplikasi berfungsi seperti yang diharapkan. Di dasbor .NET.NET Aspire, tunggu hingga semua sumber daya berjalan dan sehat. Kemudian pilih titik akhir https Swagger dan uji titik akhir GET /api/SupportTickets API dengan memperluas operasi dan memilih Cobalah. Pilih Jalankan untuk mengirim permintaan dan melihat respons:
[
{
"id": 1,
"title": "Initial Ticket",
"description": "Test ticket, please ignore."
}
]
Tutup tab browser yang menampilkan titik akhir Swagger dan dasbor .NET.NET Aspire lalu hentikan debugging.
Buat migrasi
Mulailah dengan membuat beberapa migrasi yang perlu diterapkan.
Buka terminal (Ctrl+` di Visual Studio).
Atur SupportTicketApi\SupportTicketApi.Api sebagai direktori saat ini.
Gunakan alat baris perintah
dotnet ef
untuk membuat migrasi baru untuk mengambil status awal skema database:dotnet ef migrations add InitialCreate --project ..\SupportTicketApi.Data\SupportTicketApi.Data.csproj
Perintah yang dilaksanakan:
- Menjalankan alat migrasi baris perintah EF Core di direktori SupportTicketApi.Api.
dotnet ef
dijalankan di lokasi ini karena layanan API adalah tempat konteks DB digunakan. - Membuat migrasi bernama InitialCreate.
- Membuat migrasi di folder Migrations dalam proyek SupportTicketApi.Data.
- Menjalankan alat migrasi baris perintah EF Core di direktori SupportTicketApi.Api.
Ubah model sehingga menyertakan properti baru. Buka SupportTicketApi.Data\Models\SupportTicket.cs dan tambahkan properti baru ke kelas
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; } }
Buat migrasi baru lainnya untuk mengambil perubahan pada model:
dotnet ef migrations add AddCompleted --project ..\SupportTicketApi.Data\SupportTicketApi.Data.csproj
Sekarang Anda memiliki beberapa migrasi yang perlu diterapkan. Selanjutnya, Anda akan membuat layanan migrasi yang menerapkan migrasi ini selama pengaktifan aplikasi.
Membuat layanan migrasi
Untuk menjalankan migrasi saat startup, Anda perlu membuat layanan yang menerapkan migrasi.
Tambahkan proyek Worker Service baru ke solusi. Jika menggunakan Visual Studio, klik kanan solusi di Penjelajah Solusi dan pilih Add>New Project. Pilih Worker Service, beri nama SupportTicketApi.MigrationService proyek dan target .NET 8.0. Jika menggunakan baris perintah, gunakan perintah berikut dari direktori solusi:
dotnet new worker -n SupportTicketApi.MigrationService -f "net8.0" dotnet sln add SupportTicketApi.MigrationService
Tambahkan referensi proyek SupportTicketApi.Data dan SupportTicketApi.ServiceDefaults ke proyek SupportTicketApi.MigrationService menggunakan Visual Studio atau baris perintah:
dotnet add SupportTicketApi.MigrationService reference SupportTicketApi.Data dotnet add SupportTicketApi.MigrationService reference SupportTicketApi.ServiceDefaults
Tambahkan 📦Aspire. Microsoft.EntityFrameworkCore.SqlServer referensi paket NuGet ke proyek SupportTicketApi.MigrationService menggunakan Visual Studio atau baris perintah:
cd SupportTicketApi.MigrationService dotnet add package Aspire.Microsoft.EntityFrameworkCore.SqlServer -v "9.1.0"
Tambahkan baris yang disorot ke file Program.cs dalam proyek SupportTicketApi.MigrationService:
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();
Dalam kode sebelumnya:
- Metode ekstensi
AddServiceDefaults
menambahkan fungsionalitas default layanan. - Metode ekstensi
AddOpenTelemetry
mengonfigurasi fungsionalitas OpenTelemetry. - Metode ekstensi
AddSqlServerDbContext
menambahkan layananTicketContext
ke kumpulan layanan. Layanan ini digunakan untuk menjalankan migrasi dan menyemai database.
- Metode ekstensi
Ganti konten file Worker.cs dalam proyek SupportTicketApi.MigrationService dengan kode berikut:
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); }); } }
Dalam kode sebelumnya:
- Metode
ExecuteAsync
dipanggil ketika pekerja memulai. Pada gilirannya melakukan langkah-langkah berikut:- Mendapatkan referensi layanan
TicketContext
dari penyedia layanan. - Menjalankan
RunMigrationAsync
untuk menerapkan migrasi yang belum diselesaikan. - Memanggil
SeedDataAsync
untuk menyemai database dengan data awal. - Menghentikan pekerja menggunakan
StopApplication
.
- Mendapatkan referensi layanan
- Metode
RunMigrationAsync
danSeedDataAsync
keduanya merangkum operasi database masing-masing menggunakan strategi eksekusi untuk menangani kesalahan sementara yang mungkin terjadi saat berinteraksi dengan database. Untuk mempelajari selengkapnya tentang strategi eksekusi, lihat Ketahanan Koneksi .
- Metode
Pasang layanan migrasi ke orkestrator
Layanan migrasi dibuat, tetapi perlu ditambahkan ke host aplikasi .NET.NET Aspire sehingga berjalan saat aplikasi dimulai.
Dalam proyek SupportTicketApi.AppHost, buka file Program.cs.
Tambahkan kode yang disorot berikut ke metode
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();
Ini mendaftarkan proyek SupportTicketApi.MigrationService sebagai layanan di host aplikasi .NET.NET Aspire.
Jika kode tidak dapat menyelesaikan proyek layanan migrasi, tambahkan referensi ke proyek layanan migrasi di proyek AppHost:
dotnet add SupportTicketApi.AppHost reference SupportTicketApi.MigrationService
Penting
Jika Anda menggunakan Visual Studio, dan Anda memilih opsi Enlist in Aspire orchestration saat membuat proyek Worker Service, kode serupa ditambahkan secara otomatis dengan nama layanan
supportticketapi-migrationservice
. Ganti kode tersebut dengan kode sebelumnya.
Hapus kode penanaman yang ada
Karena layanan migrasi menyemai database, Anda harus menghapus kode penyemaian data yang ada dari proyek API.
Dalam proyek SupportTicketApi.Api, buka file Program.cs.
Hapus baris yang disorot.
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(); } } }
Menguji layanan migrasi
Sekarang setelah layanan migrasi dikonfigurasi, jalankan aplikasi untuk menguji migrasi.
Jalankan aplikasi dan amati dasbor SupportTicketApi.
Setelah menunggu sebentar, status layanan
migrations
akan menampilkan Selesai.Pilih ikon Console logs pada layanan migrasi untuk menyelidiki log yang menunjukkan perintah SQL yang dijalankan.
Dapatkan kode
Anda dapat menemukan aplikasi sampel selesai di GitHub.
Kode sampel lainnya
Aplikasi sampel Aspire Shop menggunakan pendekatan ini untuk menerapkan migrasi. Lihat proyek AspireShop.CatalogDbManager
untuk implementasi layanan migrasi.
.NET Aspire