Rollback Entity Framework dan hapus migrasi buruk

174

Saya menggunakan EF 6.0 untuk proyek saya di C # dengan migrasi dan pembaruan manual. Saya memiliki sekitar 5 migrasi pada basis data, tetapi saya menyadari bahwa migrasi terakhir buruk dan saya tidak menginginkannya. Saya tahu bahwa saya dapat mengembalikan ke migrasi sebelumnya, tetapi ketika saya menambahkan migrasi baru (tetap) dan menjalankan Pembaruan-Database, bahkan migrasi buruk pun diterapkan.

Saya mencoba untuk mengembalikan ke migrasi sebelumnya dan menghapus file dengan migrasi buruk. Tetapi kemudian, ketika saya mencoba untuk menambahkan migrasi baru, saya mendapatkan kesalahan saat memperbarui database, karena file migrasi rusak (lebih khusus, baris kode pertama mengubah nama tabel A ke B dan baris berikutnya, EF sedang mencoba untuk memperbarui tabel dengan nama A - mungkin itu adalah beberapa bug EF).

Apakah ada beberapa pertanyaan yang dapat saya jalankan, yang akan memberi tahu EF sesuatu seperti "Lupakan migrasi terakhir seperti itu tidak pernah ada, itu buruk"? Sesuatu seperti Remove-Migration.

Sunting1 Saya menemukan solusi yang cocok untuk saya. Mengubah model ke kondisi baik dan jalankan Add-Migration TheBadMigration -Force. Ini akan mengatur ulang migrasi terakhir, bukan yang diterapkan.

Bagaimanapun, ini masih belum menjawab pertanyaan asli sepenuhnya. Jika saya UpdateDatabase ke migrasi buruk, saya tidak menemukan cara yang baik bagaimana mengembalikan dan membuat migrasi baru, kecuali yang buruk.

Terima kasih

Martin Brabec
sumber
Saya harus memulai ulang studio visual dan kemudian mulai berfungsi dengan baik. Ini telah terjadi beberapa kali pada saya, selalu setelah bermain-main dengan migrasi tanpa benar-benar memperbarui database, jadi ada sesuatu yang aneh terjadi dengan tooling di sana.
Andrei Dvoynos

Jawaban:

167

Anda memiliki 2 opsi:

  • Anda dapat mengambil Down dari migrasi buruk dan memasukkannya ke dalam migrasi baru (Anda juga perlu membuat perubahan selanjutnya pada model). Ini secara efektif bergulir ke versi yang lebih baik.

    Saya menggunakan opsi ini pada hal-hal yang telah pergi ke beberapa lingkungan.

  • Opsi lainnya adalah benar-benar menjalankan Update-Database –TargetMigration: TheLastGoodMigrationterhadap basis data yang Anda gunakan dan kemudian menghapus migrasi dari solusi Anda. Ini agak alternatif hulk smash dan mengharuskan ini dilakukan terhadap database yang digunakan dengan versi yang buruk.

    Catatan: untuk mengatur ulang migrasi yang dapat Anda gunakan Add-Migration [existingname] -Force. Namun ini akan menimpa migrasi Anda yang sudah ada, jadi pastikan untuk melakukan ini hanya jika Anda telah menghapus migrasi yang ada dari database. Ini melakukan hal yang sama seperti menghapus file migrasi yang ada dan menjalankannyaadd-migration

    Saya menggunakan opsi ini saat mengembangkan.

Tidak dicintai
sumber
1
Opsi hulk smash tidak berfungsi. Saya belum menerapkan migrasi buruk ke database. Saya mencoba, tetapi tidak berhasil, karena nama tabel saya tentukan dalam pertanyaan asli. Opsi pertama yang saya tidak suka banyak, karena sepertinya saya harus mengubah kode migrasi. Jika saya melakukannya dengan buruk, saya bisa menghancurkan semuanya.
Martin Brabec
8
Jika Anda belum menerapkan migrasi buruk, maka tidak ada yang menghentikan Anda, baik menghapusnya maupun menyusun ulang atau memperbaiki migrasi yang rusak.
Tidak dicintai
4
'Hulk smash' adalah jawabannya, itu bekerja untuk saya ketika berkembang dan saya ingin menambahkan sesuatu ke migrasi yang saya lewatkan. Saya pikir alasan itu tidak berhasil untuk Martin tidak berhubungan (atau mungkin terkait dengan mengubah skema basis data secara manual)
rethenhouser2
1
@BenRethmeier sebagai aturan umum saya hanya menggunakan opsi hulk smash saat saya sedang mengembangkan. Di prod, saya selalu membuat migrasi baru untuk memperbaiki masalah ini. Alasannya adalah bahwa Anda memerlukan intervensi manual jika Anda menurunkan versi database. Saya tidak suka apa pun yang membutuhkan intervensi manual di prod.
Tidak dicintai
1
HULK SMASH !!!! --- Saya mencoba bersikap baik tetapi EF tidak bermain - Saya kembali ke yang terakhir diketahui - (File migrasi yang dicadangkan) Dihapus, Ditambahkan Migrasi - Dipaksa - Diganti nama menjadi sebelumnya dan disalin kode. Database yang diperbarui kemudian ditambahkan migrasi kedua dengan cara yang sama - tidak ada kesalahan - kembali normal
Traci
127

Karena pertanyaan menunjukkan ini berlaku untuk migrasi di lingkungan tipe pengembangan yang belum dirilis.

Masalah ini dapat dipecahkan dalam langkah-langkah ini: pulihkan basis data Anda ke migrasi baik terakhir, hapus migrasi buruk dari proyek Entity Framework Anda, hasilkan migrasi baru dan terapkan ke database. Catatan: Dilihat dari komentar, perintah yang tepat ini mungkin tidak lagi berlaku jika Anda menggunakan EF Core.

Langkah 1: Kembalikan ke migrasi sebelumnya

Jika Anda belum menerapkan migrasi Anda, Anda dapat melewati bagian ini. Untuk mengembalikan skema database Anda ke masalah poin sebelumnya, perintah Update-Database dengan opsi -TargetMigration menentukan migrasi baik terakhir. Jika kode kerangka kerja Anda berada di proyek yang berbeda dalam solusi Anda, Anda mungkin perlu menggunakan opsi '-Proyek' atau mengganti proyek default di konsol manajer paket.

Update-Database TargetMigration: <name of last good migration>

Untuk mendapatkan nama migrasi baik terakhir, gunakan perintah 'Dapatkan-Migrasi' untuk mengambil daftar nama migrasi yang telah diterapkan ke database Anda.

PM> Get-Migrations
Retrieving migrations that have been applied to the target database.
201508242303096_Bad_Migration
201508211842590_The_Migration_applied_before_it
201508211440252_And_another

Daftar ini menunjukkan migrasi yang diterapkan paling baru terlebih dahulu. Pilih migrasi yang terjadi dalam daftar setelah yang ingin Anda downgrade, yaitu yang diterapkan sebelum yang Anda ingin downgrade. Sekarang keluarkan Update-Database.

Update-Database TargetMigration: "<the migration applied before it>"

Semua migrasi yang diterapkan setelah yang ditentukan akan diturunkan peringkatnya agar dimulai dengan migrasi terbaru yang diterapkan terlebih dahulu.

Langkah 2: Hapus migrasi Anda dari proyek

remove-migration name_of_bad_migration

Jika remove-migrationperintah tidak tersedia di versi Entity Framework Anda, hapus file migrasi yang tidak diinginkan folder 'Migrasi' proyek EF Anda secara manual. Pada titik ini, Anda bebas untuk membuat migrasi baru dan menerapkannya ke database.

Langkah 3: Tambahkan migrasi baru Anda

add-migration my_new_migration

Langkah 4: Terapkan migrasi Anda ke database

update-database
David Sopko
sumber
6
Dengan EF Core, sepertinya Get-Migrations telah dihapus.
Kevin Burton
1
Langkah 2 ! - Fitur yang sangat berguna. Seperti @KevinBurton sebutkan. Dan kemudian add-migration "new migration",update-database
Alexander Frolov
2
Pembaruan-Database-migrasi: "<migrasi diterapkan sebelum itu>" @ David Sopko
Fuat
Terima kasih @AlexanderFrolov saya memperbarui solusi untuk mencerminkan komentar Anda.
David Sopko
1
kita perlu menggunakan penghapusan migrasi setelah langkah 2
Rahul
55

Bagi mereka yang menggunakan EF Core dengan ASP.NET Core v1.0.0 Saya memiliki masalah yang sama dan menggunakan perintah berikut untuk memperbaikinya (posting @ DavidSopko menunjuk saya ke arah yang benar, tetapi detailnya sedikit berbeda untuk EF Core) :

Update-Database <Name of last good migration>
Remove-Migration

Sebagai contoh, dalam perkembangan saya saat ini perintah menjadi

PM> Update-Database CreateInitialDatabase
Done.
PM> Remove-Migration
Done.
PM> 

Remove-Migration akan menghapus migrasi terakhir yang Anda lamar. Jika Anda memiliki skenario yang lebih kompleks dengan beberapa migrasi untuk dihapus (saya hanya punya 2, yang awal dan yang buruk), saya sarankan Anda menguji langkah-langkah dalam proyek dummy.

Saat ini tampaknya tidak ada perintah Get-Migrations di EF Core (v1.0.0) sehingga Anda harus melihat di folder migrasi Anda dan memahami apa yang telah Anda lakukan. Namun, ada perintah bantuan yang bagus:

PM> get-help entityframework

Menyegarkan dastabase di VS2015 SQL Server Object Explorer, semua data saya terpelihara dan migrasi yang ingin saya kembalikan hilang :)

Awalnya saya mencoba Remove-Migration dengan sendirinya dan menemukan perintah error membingungkan:

System.InvalidOperationException: Migrasi '...' telah diterapkan ke database. Hapus penerapannya dan coba lagi. Jika migrasi telah diterapkan ke database lain, pertimbangkan untuk mengembalikan perubahannya menggunakan migrasi baru.

Sudah ada saran untuk meningkatkan kata-kata ini, tapi saya ingin kesalahan mengatakan sesuatu seperti ini:

Jalankan Update-Database (nama migrasi terakhir yang baik) untuk mengembalikan skema database kembali ke keadaan itu. Perintah ini akan menghapus semua migrasi yang terjadi setelah migrasi yang ditentukan ke Pembaruan-Database. Anda kemudian dapat menjalankan Hapus-Migrasi (nama migrasi untuk dihapus)

Output dari perintah bantuan EF Core berikut:

 PM> get-help entityframework
                     _/\__
               ---==/    \\
         ___  ___   |.    \|\
        | __|| __|  |  )   \\\
        | _| | _|   \_/ |  //|\\
        |___||_|       /   \\\/\\

TOPIC
    about_EntityFrameworkCore

SHORT DESCRIPTION
    Provides information about Entity Framework Core commands.

LONG DESCRIPTION
    This topic describes the Entity Framework Core commands. See https://docs.efproject.net for information on Entity Framework Core.

    The following Entity Framework cmdlets are included.

        Cmdlet                      Description
        --------------------------  ---------------------------------------------------
        Add-Migration               Adds a new migration.

        Remove-Migration            Removes the last migration.

        Scaffold-DbContext          Scaffolds a DbContext and entity type classes for a specified database.

        Script-Migration            Generates a SQL script from migrations.

        Update-Database             Updates the database to a specified migration.

        Use-DbContext               Sets the default DbContext to use.

SEE ALSO
    Add-Migration
    Remove-Migration
    Scaffold-DbContext
    Script-Migration
    Update-Database
    Use-DbContext
Richard Logwood
sumber
6

Anda juga bisa menggunakan

Remove-Migration -Force

Ini akan mengembalikan dan menghapus migrasi terapan terakhir

Daniël Tulp
sumber
4

Pertama, Perbarui migrasi sempurna terakhir Anda melalui perintah ini:

Update-Database TargetMigration

Contoh:

Update-Database -20180906131107_xxxx_xxxx

Dan, kemudian hapus migrasi Anda yang tidak digunakan secara manual.

Abdus Salam Azad
sumber
2
seharusnya: Update-Database -TargetMigration 20180906131107_xxxx_xxxx
Elger Mensonides
Update-Database 20180906131107_xxxx_xxxx(tanpa tanda hubung) bekerja untuk saya. Tidak ada versi TargetMigrationsebagai saklar yang berfungsi. Perintah-perintah ini tampaknya menjadi target yang bergerak (yaitu mengubahnya di setiap versi)?
Jumlah Tidak Ada
3

Pada .NET Core 2.2, TargetMigrationtampaknya hilang:

get-help Update-Database

NAME
    Update-Database

SYNOPSIS
    Updates the database to a specified migration.


SYNTAX
    Update-Database [[-Migration] <String>] [-Context <String>] [-Project <String>] [-StartupProject <String>] [<CommonParameters>]


DESCRIPTION
    Updates the database to a specified migration.


RELATED LINKS
    Script-Migration
    about_EntityFrameworkCore 

REMARKS
    To see the examples, type: "get-help Update-Database -examples".
    For more information, type: "get-help Update-Database -detailed".
    For technical information, type: "get-help Update-Database -full".
    For online help, type: "get-help Update-Database -online"

Jadi ini bekerja untuk saya sekarang:

Update-Database -Migration 20180906131107_xxxx_xxxx

Serta (tidak ada -Migrationsaklar):

Update-Database 20180906131107_xxxx_xxxx

Pada catatan tambahan, Anda tidak lagi dapat menghapus folder migrasi tanpa menyinkronkan Snapshot Model Anda. Jadi jika Anda mempelajari ini dengan cara yang sulit dan berakhir dengan migrasi kosong di mana Anda tahu harus ada perubahan, Anda dapat menjalankan (tidak ada switch yang diperlukan untuk migrasi terakhir):

Remove-migration

Ini akan membersihkan kekacauan dan mengembalikan Anda ke tempat yang Anda inginkan, meskipun folder migrasi terakhir dihapus secara manual.

Jumlah tidak ada
sumber
0

Untuk EF 6, ini adalah one-liner jika Anda banyak merancah dalam pengembangan. Cukup perbarui vars lalu terus gunakan panah atas di konsol manajer paket untuk membilas dan mengulangi.

$lastGoodTarget = "OldTargetName"; $newTarget = "NewTargetName"; Update-Database -TargetMigration "$lastGoodTarget" -Verbose; Add-Migration "$newTarget" -Verbose -Force

Mengapa ini perlu Anda tanyakan? Tidak yakin versi EF6 mana yang berlaku, tetapi jika target migrasi baru Anda telah diterapkan, maka gunakan '-Paksa' untuk kembali scaffold di Add-Migration tidak akan benar-benar scaffold, tetapi sebaliknya membuat file baru (ini bagus Hal itu karena Anda tidak ingin kehilangan 'Down' Anda). Cuplikan di atas melakukan 'Down' terlebih dahulu jika perlu maka -Force berfungsi dengan baik untuk kembali scaffold.

misi
sumber