Menerapkan Migrasi

Setelah migrasi Anda ditambahkan, migrasi perlu disebarkan dan diterapkan ke database Anda. Ada berbagai strategi untuk melakukan ini, dengan beberapa lebih sesuai untuk lingkungan produksi, dan yang lain untuk siklus hidup pengembangan.

Catatan

Apa pun strategi penyebaran Anda, selalu periksa migrasi yang dihasilkan dan uji sebelum diterapkan ke database produksi. Migrasi dapat menghilangkan kolom saat niatnya adalah mengganti namanya, atau mungkin gagal karena berbagai alasan saat diterapkan ke database.

Skrip SQL

Cara yang disarankan untuk menyebarkan migrasi ke database produksi adalah dengan menghasilkan skrip SQL. Keuntungan dari strategi ini meliputi:

  • Skrip SQL dapat ditinjau untuk akurasi; ini penting karena menerapkan perubahan skema pada database produksi adalah operasi yang berpotensi berbahaya yang dapat melibatkan kehilangan data.
  • Dalam beberapa kasus, skrip dapat disetel agar sesuai dengan kebutuhan spesifik database produksi.
  • Skrip SQL dapat digunakan bersama dengan teknologi penyebaran, dan bahkan dapat dihasilkan sebagai bagian dari proses CI Anda.
  • Skrip SQL dapat disediakan untuk DBA, dan dapat dikelola dan diarsipkan secara terpisah.

Penggunaan Dasar

Berikut ini menghasilkan skrip SQL dari database kosong ke migrasi terbaru:

dotnet ef migrations script

Dengan Dari (ke tersirat)

Berikut ini menghasilkan skrip SQL dari migrasi yang diberikan ke migrasi terbaru.

dotnet ef migrations script AddNewTables

Dengan Dari dan Ke

Berikut ini menghasilkan skrip SQL dari migrasi yang ditentukan from ke migrasi yang ditentukan to .

dotnet ef migrations script AddNewTables AddAuditTable

Anda dapat menggunakan from yang lebih baru dari to untuk menghasilkan skrip putar kembali.

Peringatan

Harap perhatikan potensi skenario kehilangan data.

Pembuatan skrip menerima dua argumen berikut untuk menunjukkan rentang migrasi mana yang harus dihasilkan:

  • Migrasi dari harus menjadi migrasi terakhir yang diterapkan ke database sebelum menjalankan skrip. Jika tidak ada migrasi yang diterapkan, tentukan 0 (ini adalah default).
  • Migrasi ke adalah migrasi terakhir yang akan diterapkan ke database setelah menjalankan skrip. Ini default ke migrasi terakhir dalam proyek Anda.

Skrip SQL Idempotent

Skrip SQL yang dihasilkan di atas hanya dapat diterapkan untuk mengubah skema Anda dari satu migrasi ke migrasi lainnya; Anda bertanggung jawab untuk menerapkan skrip dengan tepat, dan hanya ke database dalam status migrasi yang benar. EF Core juga mendukung pembuatan skrip idempogen , yang secara internal memeriksa migrasi mana yang telah diterapkan (melalui tabel riwayat migrasi), dan hanya menerapkan yang hilang. Ini berguna jika Anda tidak benar-benar tahu apa migrasi terakhir yang diterapkan ke database, atau jika Anda menyebarkan ke beberapa database yang mungkin masing-masing berada di migrasi yang berbeda.

Berikut ini menghasilkan migrasi idempogen:

dotnet ef migrations script --idempotent

Alat baris perintah

Alat baris perintah EF dapat digunakan untuk menerapkan migrasi ke database. Meskipun produktif untuk pengembangan lokal dan pengujian migrasi, pendekatan ini tidak ideal untuk mengelola database produksi:

  • Perintah SQL diterapkan langsung oleh alat, tanpa memberi pengembang kesempatan untuk memeriksa atau memodifikasinya. Ini bisa berbahaya di lingkungan produksi.
  • .NET SDK dan alat EF harus diinstal pada server produksi dan memerlukan kode sumber proyek.

Catatan

Setiap migrasi diterapkan dalam transaksinya sendiri. Lihat masalah GitHub #22616 untuk diskusi tentang kemungkinan peningkatan di masa mendatang di area ini.

Berikut ini memperbarui database Anda ke migrasi terbaru:

dotnet ef database update

Berikut ini memperbarui database Anda ke migrasi tertentu:

dotnet ef database update AddNewTables

Perhatikan bahwa ini juga dapat digunakan untuk mengembalikan ke migrasi sebelumnya.

Peringatan

Harap perhatikan potensi skenario kehilangan data.

Untuk informasi selengkapnya tentang menerapkan migrasi melalui alat baris perintah, lihat referensi alat EF Core.

Bundel

Bundel migrasi adalah file tunggal yang dapat dieksekusi yang dapat digunakan untuk menerapkan migrasi ke database. Mereka mengatasi beberapa kekurangan skrip SQL dan alat baris perintah:

  • Menjalankan skrip SQL memerlukan alat tambahan.
  • Penanganan transaksi dan perilaku kesalahan berkelanjutan dari alat-alat ini tidak konsisten dan terkadang tidak terduga. Ini dapat membiarkan database Anda dalam status tidak terdefinisi jika kegagalan terjadi saat menerapkan migrasi.
  • Bundel dapat dihasilkan sebagai bagian dari proses CI Anda dan dengan mudah dijalankan nanti sebagai bagian dari proses penyebaran Anda.
  • Bundel dapat dijalankan tanpa menginstal .NET SDK atau EF Tool (atau bahkan .NET Runtime, saat mandiri), dan tidak memerlukan kode sumber proyek.

Berikut ini menghasilkan bundel:

dotnet ef migrations bundle

Berikut ini menghasilkan bundel mandiri untuk Linux:

dotnet ef migrations bundle --self-contained -r linux-x64

Untuk informasi selengkapnya tentang membuat bundel, lihat referensi alat EF Core.

efbundle

Executable yang dihasilkan dinamai efbundle secara default. Ini dapat digunakan untuk memperbarui database ke migrasi terbaru. Ini setara dengan menjalankan dotnet ef database update atau Update-Database.

Argumen:

Argumen Deskripsi
<MIGRATION> Migrasi target. Jika '0', semua migrasi akan dikembalikan. Default ke migrasi terakhir.

Opsi:

Opsi Pendek Deskripsi
--connection <CONNECTION> string koneksi ke database. Default ke yang ditentukan dalam AddDbContext atau OnConfiguring.
--verbose -v Tampilkan output verbose.
--no-color Jangan mewarnai output.
--prefix-output Output awalan dengan tingkat.

Contoh berikut menerapkan migrasi ke instans SQL Server lokal menggunakan nama pengguna dan kata sandi yang ditentukan.

.\efbundle.exe --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;User ID=myUsername;Password=myPassword'

Peringatan

Jangan lupa untuk menyalin appsettings.json bersama bundel Anda. Bundel bergantung pada keberadaan appsettings.json di direktori eksekusi.

Contoh bundel migrasi

Bundel memerlukan migrasi untuk disertakan. Ini dibuat menggunakan dotnet ef migrations add seperti yang dijelaskan dalam Membuat migrasi pertama Anda. Setelah Anda memiliki migrasi yang siap disebarkan, buat bundel menggunakan dotnet ef migrations bundle. Misalnya:

PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations bundle
Build started...
Build succeeded.
Building bundle...
Done. Migrations Bundle: C:\local\AllTogetherNow\SixOh\efbundle.exe
PS C:\local\AllTogetherNow\SixOh>

Output adalah executable yang cocok untuk sistem operasi target Anda. Dalam kasus saya ini adalah Windows x64, jadi saya mendapatkan dihilangkan efbundle.exe di folder lokal saya. Menjalankan executable ini menerapkan migrasi yang terkandung di dalamnya:

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903083845_MyMigration'.
Done.
PS C:\local\AllTogetherNow\SixOh>

dotnet ef database update Seperti halnya atau Update-Database, migrasi diterapkan ke database hanya jika belum diterapkan. Misalnya, menjalankan bundel yang sama lagi tidak melakukan apa-apa, karena tidak ada migrasi baru untuk diterapkan:

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
No migrations were applied. The database is already up to date.
Done.
PS C:\local\AllTogetherNow\SixOh>

Namun, jika perubahan dilakukan pada model dan lebih banyak migrasi dihasilkan dengan dotnet ef migrations add, maka ini dapat dibundel ke dalam executable baru yang siap diterapkan. Misalnya:

PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations add SecondMigration
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations add Number3
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations bundle --force
Build started...
Build succeeded.
Building bundle...
Done. Migrations Bundle: C:\local\AllTogetherNow\SixOh\efbundle.exe
PS C:\local\AllTogetherNow\SixOh>

Tip

Opsi --force dapat digunakan untuk menimpa bundel yang ada dengan yang baru.

Menjalankan bundel baru ini menerapkan dua migrasi baru ini ke database:

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903084526_SecondMigration'.
Applying migration '20210903084538_Number3'.
Done.
PS C:\local\AllTogetherNow\SixOh>

Secara default, bundel menggunakan database string koneksi dari konfigurasi aplikasi Anda. Namun, database yang berbeda dapat dimigrasikan dengan melewati string koneksi pada baris perintah. Contoh:

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe --connection "Data Source=(LocalDb)\MSSQLLocalDB;Database=SixOhProduction"
Applying migration '20210903083845_MyMigration'.
Applying migration '20210903084526_SecondMigration'.
Applying migration '20210903084538_Number3'.
Done.
PS C:\local\AllTogetherNow\SixOh>

Catatan

Kali ini, ketiga migrasi diterapkan, karena belum ada yang diterapkan ke database produksi.


Menerapkan migrasi pada runtime

Aplikasi itu sendiri dapat menerapkan migrasi secara terprogram, biasanya selama startup. Meskipun produktif untuk pengembangan lokal dan pengujian migrasi, pendekatan ini tidak pantas untuk mengelola database produksi, karena alasan berikut:

  • Jika beberapa instans aplikasi Anda berjalan, kedua aplikasi dapat mencoba menerapkan migrasi secara bersamaan dan gagal (atau lebih buruk, menyebabkan kerusakan data).
  • Demikian pula, jika aplikasi mengakses database saat aplikasi lain memigrasikannya, ini dapat menyebabkan masalah parah.
  • Aplikasi harus memiliki akses yang ditingkatkan untuk mengubah skema database. Ini umumnya praktik yang baik untuk membatasi izin database aplikasi dalam produksi.
  • Penting untuk dapat mengembalikan migrasi yang diterapkan jika terjadi masalah. Strategi lain menyediakan ini dengan mudah dan langsung.
  • Perintah SQL diterapkan langsung oleh program, tanpa memberi pengembang kesempatan untuk memeriksa atau memodifikasinya. Ini bisa berbahaya di lingkungan produksi.

Untuk menerapkan migrasi secara terprogram, panggil context.Database.Migrate(). Misalnya, aplikasi ASP.NET umum dapat melakukan hal berikut:

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    using (var scope = host.Services.CreateScope())
    {
        var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
        db.Database.Migrate();
    }

    host.Run();
}

Perhatikan bahwa Migrate() dibangun di atas IMigrator layanan, yang dapat digunakan untuk skenario yang lebih canggih. Gunakan myDbContext.GetInfrastructure().GetService<IMigrator>() untuk mengaksesnya.

Peringatan

  • Pertimbangkan dengan cermat sebelum menggunakan pendekatan ini dalam produksi. Pengalaman telah menunjukkan bahwa kesederhanaan strategi penyebaran ini lebih besar dari masalah yang dibuatnya. Pertimbangkan untuk membuat skrip SQL dari migrasi sebagai gantinya.
  • Jangan menelepon EnsureCreated() sebelum Migrate(). EnsureCreated() melewati Migrasi untuk membuat skema, yang menyebabkan Migrate() kegagalan.