Entity Framework revierte y elimina la migración incorrecta

174

Estoy usando EF 6.0 para mi proyecto en C # con migraciones manuales y actualizaciones. Tengo alrededor de 5 migraciones en la base de datos, pero me di cuenta de que la última migración fue mala y no la quiero. Sé que puedo retroceder a una migración anterior, pero cuando agrego una nueva migración (fija) y ejecuto Update-Database, incluso se aplica la migración incorrecta.

Estaba tratando de retroceder a la migración anterior y eliminar el archivo con una migración incorrecta. Pero luego, cuando intento agregar una nueva migración, recibo un error al actualizar la base de datos, porque el archivo de migración está dañado (más específicamente, la primera línea de código cambia el nombre de la tabla A a B y las líneas siguientes, EF está tratando de actualizar la tabla con nombre A: tal vez es un error de EF).

¿Hay alguna consulta que pueda ejecutar, que le diga a EF algo como "Olvidar la última migración como nunca existió, fue malo"? Algo como Eliminar-Migración.

Edit1 encontré la solución adecuada para mí. Cambio de modelo al buen estado y ejecución Add-Migration TheBadMigration -Force. Esto volverá a andamiar la última migración no aplicada.

De todos modos, esto todavía no responde la pregunta original por completo. Si actualizo Database a la mala migración, no encontré una buena manera de deshacer y crear una nueva migración, excluyendo la mala.

Gracias

Martin Brabec
fuente
Tuve que reiniciar Visual Studio y luego comenzó a funcionar correctamente. Esto ya me ha pasado un par de veces, siempre después de jugar con las migraciones sin actualizar la base de datos, por lo que sucede algo extraño con las herramientas allí.
Andrei Dvoynos

Respuestas:

167

Tienes 2 opciones:

  • Puede quitar el Down de la migración incorrecta y colocarlo en una nueva migración (también deberá realizar los cambios posteriores en el modelo). Esto está efectivamente llegando a una mejor versión.

    Utilizo esta opción en cosas que han ido a múltiples entornos.

  • La otra opción es ejecutar realmente Update-Database –TargetMigration: TheLastGoodMigrationcontra su base de datos desplegada y luego eliminar la migración de su solución. Esta es la alternativa de Hulk Smash y requiere que esto se realice en cualquier base de datos implementada con la versión incorrecta.

    Nota: para reorganizar la migración que puede usar Add-Migration [existingname] -Force. Sin embargo, esto sobrescribirá su migración existente, así que asegúrese de hacerlo solo si ha eliminado la migración existente de la base de datos. Esto hace lo mismo que eliminar el archivo de migración existente y ejecutaradd-migration

    Yo uso esta opción mientras desarrollo.

No amado
fuente
1
La opción Hulk Smash no funciona. Todavía no apliqué la mala migración a la base de datos. Lo intenté, pero no funcionaba, porque los nombres de tabla que especifiqué en la pregunta original. La primera opción no me gusta mucho, porque parece que tendría que cambiar el código de la migración. Si lo hago mal, puedo romperlo todo.
Martin Brabec
8
Si aún no ha aplicado la migración incorrecta, no hay nada que lo detenga, ya sea eliminándola y volviendo a encapsular o corrigiendo la migración rota.
No amado
44
La respuesta es 'hulk smash', me funciona cuando desarrollo y quiero agregar algo a la migración que me perdí. Creo que las razones no funcionó para Martin no están relacionados (o probablemente relacionadas con el cambio del esquema de base de datos manualmente)
rethenhouser2
1
@BenRethmeier como regla general, uso la opción hulk smash solo mientras estoy desarrollando. En prod, siempre creo una nueva migración para corregir el problema. La razón es que necesita intervención manual si está degradando la base de datos. No me gusta nada que necesite intervención manual en productos.
No amado
1
HULK SMASH !!!! --- Traté de ser amable pero EF no estaba jugando - volví a la última conocida - (Copia de seguridad de los archivos de migración) Eliminado, Agregado Migración - Fuerza - Renombrado a anterior y copié el código. la segunda migración de la misma manera - sin errores - de vuelta a la normalidad
Traci
127

Como la pregunta indica, esto se aplica a una migración en un entorno de tipo de desarrollo que aún no se ha lanzado.

Este problema se puede resolver en estos pasos: restaure su base de datos a la última migración correcta, elimine la migración incorrecta de su proyecto de Entity Framework, genere una nueva migración y aplíquela a la base de datos. Nota: a juzgar por los comentarios, estos comandos exactos pueden dejar de ser aplicables si está utilizando EF Core.

Paso 1: Restaurar a una migración anterior

Si aún no ha aplicado su migración, puede omitir esta parte. Para restaurar el esquema de su base de datos a un punto anterior, emita el comando Actualizar-Base de datos con la opción -TargetMigration para especificar la última migración correcta. Si su código de marco de entidad reside en un proyecto diferente en su solución, es posible que deba usar la opción '-Proyecto' o cambiar el proyecto predeterminado en la consola del administrador de paquetes.

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

Para obtener el nombre de la última buena migración, use el comando 'Get-Migrations' para recuperar una lista de los nombres de migración que se han aplicado a su base de datos.

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

Esta lista muestra primero las migraciones aplicadas más recientes. Elija la migración que se produce en la lista después de la que desea degradar, es decir, la que se aplica antes de la que desea degradar. Ahora emita una base de datos de actualización.

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

Todas las migraciones aplicadas después de la especificada se degradarán para comenzar con la última migración aplicada primero.

Paso 2: elimine su migración del proyecto

remove-migration name_of_bad_migration

Si el remove-migrationcomando no está disponible en su versión de Entity Framework, elimine manualmente los archivos de la migración no deseada de la carpeta 'Migraciones' de su proyecto EF. En este punto, puede crear una nueva migración y aplicarla a la base de datos.

Paso 3: agrega tu nueva migración

add-migration my_new_migration

Paso 4: aplique su migración a la base de datos

update-database
David Sopko
fuente
66
Con EF Core parece que Get-Migrations ha sido eliminado.
Kevin Burton el
1
Paso 2 ! - Característica muy útil. Como @KevinBurton mencionó. Y luego add-migration "new migration",update-database
Alexander Frolov
2
Update-Database –migration: "<la migración aplicada antes que ella>" @David Sopko
Fuat
Gracias @AlexanderFrolov Actualicé la solución para reflejar sus comentarios.
David Sopko el
1
necesitamos usar remove-migración después del paso 2
Rahul
55

Para aquellos que usan EF Core con ASP.NET Core v1.0.0 , tuve un problema similar y utilicé los siguientes comandos para corregirlo (la publicación de @ DavidSopko me señaló en la dirección correcta, pero los detalles son ligeramente diferentes para EF Core) :

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

Por ejemplo, en mi desarrollo actual, el comando se convirtió en

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

Remove-Migration eliminará la última migración que aplicó. Si tiene un escenario más complejo con múltiples migraciones para eliminar (solo tuve 2, la inicial y la mala), le sugiero que pruebe los pasos en un proyecto ficticio.

Actualmente no parece haber un comando Get-Migrations en EF Core (v1.0.0), por lo que debe buscar en su carpeta de migraciones y estar familiarizado con lo que ha hecho. Sin embargo, hay un buen comando de ayuda:

PM> get-help entityframework

Al actualizar la base de datos en VS2015 SQL Server Object Explorer, todos mis datos se conservaron y la migración que quería revertir desapareció :)

Inicialmente probé Remove-Migration solo y encontré el comando de error confuso:

System.InvalidOperationException: la migración '...' ya se ha aplicado a la base de datos. No aplique e intente nuevamente. Si la migración se ha aplicado a otras bases de datos, considere revertir sus cambios utilizando una nueva migración.

Ya hay sugerencias para mejorar esta redacción, pero me gustaría que el error diga algo como esto:

Ejecute Update-Database (último buen nombre de migración) para revertir el esquema de la base de datos a ese estado. Este comando no aplicará todas las migraciones que ocurrieron después de la migración especificada a Update-Database. Luego puede ejecutar Remove-Migration (nombre de migración para eliminar)

La salida del comando de ayuda de EF Core sigue:

 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
fuente
6

También puedes usar

Remove-Migration -Force

Esto revertirá y eliminará la última migración aplicada

Daniël Tulp
fuente
4

Primero, actualice su última migración perfecta con este comando:

Update-Database TargetMigration

Ejemplo:

Update-Database -20180906131107_xxxx_xxxx

Y, luego, elimine la migración no utilizada manualmente.

Abdus Salam Azad
fuente
2
debería ser: Update-Database -TargetMigration 20180906131107_xxxx_xxxx
Elger Mensonides
Update-Database 20180906131107_xxxx_xxxx(sin guión) funcionó para mí. Ninguna versión de TargetMigrationcomo un interruptor funcionó. Estos comandos parecen ser un objetivo en movimiento (es decir, cambiarlos en cada versión)?
Suma ninguno
3

A partir de .NET Core 2.2, TargetMigrationparece haber desaparecido:

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"

Entonces esto funciona para mí ahora:

Update-Database -Migration 20180906131107_xxxx_xxxx

Además de (sin -Migrationinterruptor):

Update-Database 20180906131107_xxxx_xxxx

En una nota adicional, ya no puede eliminar limpiamente las carpetas de migración sin poner su Instantánea del modelo fuera de sincronización. Entonces, si aprende esto de la manera difícil y termina con una migración vacía donde sabe que debería haber cambios, puede ejecutar (no se necesitan interruptores para la última migración):

Remove-migration

Limpiará el desorden y lo devolverá a donde necesita estar, a pesar de que la última carpeta de migración se eliminó manualmente.

Suma ninguno
fuente
0

Para EF 6, aquí hay una línea si está volviendo a andamiar mucho en desarrollo. Simplemente actualice los vars y luego siga usando la flecha hacia arriba en la consola del administrador de paquetes para enjuagar y repetir.

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

¿Por qué es esto necesario, preguntas? No estoy seguro de qué versiones de EF6 se aplica, pero si su nuevo objetivo de migración ya se ha aplicado, el uso de '-Force' para volver a andamio en Add-Migration no volverá a andamiaje, sino que creará un nuevo archivo (este es un buen aunque porque no querrías perder tu 'Down'). El fragmento anterior hace el 'Abajo' primero si es necesario y luego -Force funciona correctamente para volver a andamiaje.

madamission
fuente