Reversão do Entity Framework e remova a migração incorreta

174

Estou usando o EF 6.0 para o meu projeto em c # com migrações e atualizações manuais. Eu tenho cerca de 5 migrações no banco de dados, mas percebi que a última migração era ruim e não a quero. Sei que posso reverter para uma migração anterior, mas quando adiciono uma nova migração (fixa) e executo o Update-Database, até a má migração é aplicada.

Eu estava tentando reverter para a migração anterior e excluir o arquivo com uma migração incorreta. Porém, quando tento adicionar nova migração, recebo um erro ao atualizar o banco de dados, porque o arquivo de migração está corrompido (mais especificamente, a primeira linha de código renomeia a tabela A para B e é a próxima linha, o EF está tentando atualizar a tabela com nome A - talvez seja algum bug da EF).

Existe alguma consulta que eu possa executar, que diria à EF algo como "Esqueça a última migração como se nunca tivesse existido, era ruim"? Algo como Remover-Migração.

Edit1 Encontrei solução adequada para mim. Alterando o modelo para o bom estado e executandoAdd-Migration TheBadMigration -Force . Isso redefinirá a última migração não aplicada.

De qualquer forma, isso ainda não responde completamente à pergunta original. Se eu atualizar o banco de dados para a migração incorreta, não encontrei uma boa maneira de reverter e criar nova migração, excluindo a incorreta.

obrigado

Martin Brabec
fonte
Eu tive que reiniciar o visual studio e ele começou a funcionar corretamente. Isso já aconteceu algumas vezes comigo, sempre depois de mexer nas migrações sem realmente atualizar o banco de dados, então há algo estranho acontecendo com as ferramentas lá.
Andrei Dvoynos 30/04/19

Respostas:

167

Você tem 2 opções:

  • Você pode tirar o Down da má migração e colocá-lo em uma nova migração (você também precisará fazer as alterações subseqüentes no modelo). Isso está rolando efetivamente para uma versão melhor.

    Eu uso essa opção em coisas que foram para vários ambientes.

  • A outra opção é realmente executar Update-Database –TargetMigration: TheLastGoodMigration o banco de dados implantado e excluir a migração da sua solução. Essa é a alternativa do hulk smash e exige que isso seja executado em qualquer banco de dados implantado com a versão ruim.

    Nota: para redefinir a migração que você pode usar Add-Migration [existingname] -Force. No entanto, isso substituirá a migração existente, portanto, faça isso somente se você tiver removido a migração existente do banco de dados. Isso faz o mesmo que excluir o arquivo de migração existente e executaradd-migration

    Eu uso essa opção durante o desenvolvimento.

Não amado
fonte
1
A opção hulk smash não funciona. Ainda não apliquei a migração incorreta para o banco de dados. Eu tentei, mas não estava funcionando, porque os nomes de tabela que especifiquei na pergunta original. A primeira opção não gosto muito, porque parece que eu teria que mudar o código da migração. Se eu fizer mal, posso quebrar tudo.
Martin Brabec 27/03
8
Se você ainda não aplicou a migração incorreta, nada o impedirá de excluí-la e reinstalar ou corrigir a migração interrompida.
Não amou
4
O 'hulk smash' é a resposta, funciona para mim no desenvolvimento e quero adicionar algo à migração que perdi. Penso que as razões não funcionou para Martin são independentes (ou provavelmente relacionadas com alteração do esquema de banco de dados manualmente)
rethenhouser2
1
@BenRethmeier como regra geral Eu uso a opção hulk smash apenas enquanto estou desenvolvendo. Na prod, eu sempre crio uma nova migração para corrigir o problema. O motivo é que você precisa de intervenção manual se estiver fazendo o downgrade do banco de dados. Não gosto de nada que precise de intervenção manual em prod.
Não amado
1
HULK SMASH !!!! --- Tentei ser legal, mas o EF não estava sendo reproduzido - eu reverti para a última vez conhecida - (Arquivos de migração de backup) Excluídos, Migração adicionada - Força - Renomeado para anterior e copiado o código. a segunda migração da mesma maneira - sem erros - de volta ao normal
Traci
127

Como a pergunta indica, isso se aplica a uma migração em um ambiente de tipo de desenvolvimento que ainda não foi lançado.

Esse problema pode ser resolvido nestas etapas: restaure o banco de dados até a última boa migração, exclua a migração incorreta do projeto do Entity Framework, gere uma nova migração e aplique-a ao banco de dados. Nota: A julgar pelos comentários, esses comandos exatos podem não ser mais aplicáveis ​​se você estiver usando o EF Core.

Etapa 1: Restaurar para uma migração anterior

Se você ainda não aplicou sua migração, pode pular esta parte. Para restaurar o esquema do banco de dados para um problema anterior, o comando Update-Database com a opção -TargetMigration especifique a última boa migração. Se o código da estrutura da sua entidade residir em um projeto diferente na sua solução, talvez você precise usar a opção '-Project' ou alternar o projeto padrão no console do gerenciador de pacotes.

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

Para obter o nome da última boa migração, use o comando 'Get-Migrations' para recuperar uma lista dos nomes de migração que foram aplicados ao seu banco de dados.

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 mostra as migrações aplicadas mais recentes primeiro. Escolha a migração que ocorre na lista após a que você deseja fazer o downgrade, ou seja, a aplicada antes da que você deseja fazer o downgrade. Agora emita um banco de dados de atualização.

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

Todas as migrações aplicadas após a especificada serão rebaixadas, começando pela última migração aplicada primeiro.

Etapa 2: excluir sua migração do projeto

remove-migration name_of_bad_migration

Se o remove-migrationcomando não estiver disponível na sua versão do Entity Framework, exclua os arquivos da migração indesejada na pasta 'Migrations' do projeto EF manualmente. Neste ponto, você pode criar uma nova migração e aplicá-la ao banco de dados.

Etapa 3: adicione sua nova migração

add-migration my_new_migration

Etapa 4: aplicar sua migração ao banco de dados

update-database
David Sopko
fonte
6
Com o EF Core, parece que o Get-Migrations foi removido.
22718 Kevin Burton
1
Passo 2 ! - Recurso muito útil. Como o @KevinBurton mencionou. E então add-migration "new migration",update-database
Alexander Frolov
2
Update-Database –migration: "<a migração aplicada antes dela" "@David Sopko
Fuat
Obrigado @AlexanderFrolov Atualizei a solução para refletir seus comentários.
David Sopko
1
precisamos usar a remoção de migração após a etapa 2
Rahul
55

Para aqueles que usam o EF Core com o ASP.NET Core v1.0.0 , tive um problema semelhante e usei os seguintes comandos para corrigi-lo (a postagem de @ DavidSopko me indicou a direção certa, mas os detalhes são um pouco diferentes para o EF Core) :

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

Por exemplo, no meu desenvolvimento atual, o comando se tornou

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

O Remove-Migration removerá a última migração que você aplicou. Se você tiver um cenário mais complexo com várias migrações para remover (eu só tinha 2, a inicial e a ruim), sugiro que você teste as etapas em um projeto fictício.

No momento, não parece haver um comando Get-Migrations no EF Core (v1.0.0), portanto, você deve procurar na pasta de migrações e estar familiarizado com o que fez. No entanto, há um bom comando de ajuda:

PM> get-help entityframework

Atualizando a dastabase no VS2015 SQL Server Object Explorer, todos os meus dados foram preservados e a migração que eu queria reverter desapareceu :)

Inicialmente, tentei o Remove-Migration por si só e achei o comando de erro confuso:

System.InvalidOperationException: a migração '...' já foi aplicada ao banco de dados. Cancele a aplicação e tente novamente. Se a migração foi aplicada a outros bancos de dados, considere reverter suas alterações usando uma nova migração.

Já existem sugestões para melhorar essa redação, mas eu gostaria que o erro dissesse algo assim:

Execute o Update-Database (último nome da boa migração) para reverter o esquema do banco de dados para esse estado. Este comando não aplicará todas as migrações que ocorreram após a migração especificada para o Update-Database. Você pode executar a opção Remove-Migration (nome da migração a remover)

A saída do comando de ajuda EF Core é a seguinte:

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

Você também pode usar

Remove-Migration -Force

Isso reverterá e removerá a última migração aplicada

Daniël Tulp
fonte
4

Primeiro, atualize sua última migração perfeita por meio deste comando:

Update-Database TargetMigration

Exemplo:

Update-Database -20180906131107_xxxx_xxxx

E, em seguida, exclua sua migração não utilizada manualmente.

Abdus Salam Azad
fonte
2
deve ser: Update-Database -TargetMigration 20180906131107_xxxx_xxxx
Elger Mensonides
Update-Database 20180906131107_xxxx_xxxx(sem hífen) funcionou para mim. Nenhuma versão do TargetMigrationswitch funcionou. Esses comandos parecem ser um alvo em movimento (ou seja, alterá-los em todas as versões)?
Soma Nenhum
3

A partir do .NET Core 2.2, TargetMigrationparece ter 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"

Então, isso funciona para mim agora:

Update-Database -Migration 20180906131107_xxxx_xxxx

Assim como (sem -Migrationchave):

Update-Database 20180906131107_xxxx_xxxx

Em uma observação adicional, você não pode mais excluir as pastas de migração de maneira limpa sem colocar o snapshot do modelo fora de sincronia. Portanto, se você aprender isso da maneira mais difícil e terminar com uma migração vazia, onde você sabe que deve haver alterações, poderá executar (não são necessárias opções para a última migração):

Remove-migration

Ele limpará a bagunça e o levará de volta onde você precisa, mesmo que a última pasta de migração tenha sido excluída manualmente.

Soma Nenhum
fonte
0

Para o EF 6, aqui está uma lista, se você estiver realizando muitas tarefas em desenvolvimento. Apenas atualize os vars e continue usando a seta para cima no console do gerenciador de pacotes para enxaguar e repetir.

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

Por que isso é necessário, você pergunta? Não tenho certeza de quais versões do EF6 isso se aplica, mas se o seu novo destino de migração já tiver sido aplicado, o uso de '-Force' para realocar novamente no Add-Migration não será realçado novamente, mas criar um novo arquivo (isso é bom coisa porque você não gostaria de perder o seu 'Down'). O snippet acima faz o 'Down' primeiro, se necessário, e então -Force funciona corretamente para re-andaime.

madamission
fonte