Откат Entity Framework и удаление плохой миграции

175

Я использую EF 6.0 для своего проекта в C # с ручными миграциями и обновлениями. У меня есть около 5 миграций в базе данных, но я понял, что последняя миграция была неудачной, и я не хочу этого. Я знаю, что могу вернуться к предыдущей миграции, но когда я добавляю новую (фиксированную) миграцию и запускаю Update-Database, применяется даже плохая миграция.

Я пытался откатиться до предыдущей миграции и удалить файл с ошибочной миграцией. Но затем, когда я пытаюсь добавить новую миграцию, я получаю ошибку при обновлении базы данных, потому что файл миграции поврежден (точнее, первая строка кода переименовывает таблицу A в B и является следующей строкой, EF пытается обновить таблицу с помощью имя А - возможно, это какая-то ошибка EF).

Могу ли я выполнить какой-нибудь запрос, который скажет EF что-то вроде «Забудьте последнюю миграцию, как будто ее никогда не было, это было плохо»? Что-то вроде Remove-Migration.

Edit1 Я нашел решение, подходящее для меня. Меняем модель до хорошего состояния и запуска Add-Migration TheBadMigration -Force. Это перенастроит последнюю, не примененную миграцию.

Во всяком случае, это все еще не полностью отвечает на первоначальный вопрос. Если я обновлю базу данных до плохой миграции, я не нашел хорошего способа откатить и создать новую миграцию, кроме плохой.

Спасибо

Мартин Брабек
источник
Мне пришлось перезапустить визуальную студию, и тогда она начала работать правильно. Это уже случалось со мной пару раз, всегда после того, как мы возились с миграциями, фактически не обновляя базу данных, поэтому с инструментарием там происходит что-то странное.
Андрей Двойнос

Ответы:

167

У вас есть 2 варианта:

  • Вы можете взять Даун из неудачной миграции и поместить его в новую миграцию (вам также необходимо будет внести последующие изменения в модель). Это эффективно сворачивается к лучшей версии.

    Я использую эту опцию для вещей, которые были в нескольких средах.

  • Другой вариант - запустить Update-Database –TargetMigration: TheLastGoodMigrationвашу развернутую базу данных, а затем удалить миграцию из вашего решения. Это своего рода альтернатива hulk smash и требует, чтобы это выполнялось для любой базы данных, развернутой с неверной версией.

    Примечание: чтобы переназначить миграцию, которую вы можете использовать Add-Migration [existingname] -Force. Это, однако, перезапишет существующую миграцию, поэтому обязательно делайте это, только если вы удалили существующую миграцию из базы данных. Это делает то же самое, что удаление существующего файла миграции и запускadd-migration

    Я использую эту опцию при разработке.

Не любил
источник
1
Опция «Халк разбить» не работает. Я еще не применил плохую миграцию к базе данных. Я пытался, но это не работало, потому что имена таблиц, которые я указал в оригинальном вопросе. Первый вариант мне не очень нравится, потому что, похоже, мне придется изменить код миграции. Если я сделаю это плохо, я могу все сломать.
Мартин Брабек
8
Если вы еще не применили неудачную миграцию, ничто не помешает вам либо удалить ее, либо переназначить, либо исправить поврежденную миграцию.
Не любил
4
«Халк разгром» - это ответ, он работает для меня при разработке, и я хочу добавить что-то к пропущенной миграции. Я думаю, что причины, по которым он не работал для Мартина, не связаны (или, возможно, связаны с изменением схемы базы данных вручную)
rethenhouser2
1
@BenRethmeier, как правило, я использую опцию hulk smash только во время разработки. В Prod я всегда создаю новую миграцию, чтобы исправить проблему. Причина в том, что вам нужно ручное вмешательство, если вы понижаете базу данных. Мне не нравится ничего, что требует ручного вмешательства в продукт.
Не любил
1
HULK SMASH !!!! --- Я пытался быть хорошим, но EF не играл - я вернулся к последнему известному - (резервные копии файлов миграции) удален, добавлен перенос - принудительно - переименован в предыдущий и скопирован код. Затем добавлена ​​база данных обновлений вторая миграция точно так же - без ошибок - вернуться к нормальной жизни
Трейси
127

Как показывает вопрос, это относится к миграции в среде типа разработки, которая еще не была выпущена.

Эта проблема может быть решена с помощью следующих шагов: восстановить вашу базу данных до последней удачной миграции, удалить неудачную миграцию из вашего проекта Entity Framework, сгенерировать новую миграцию и применить ее к базе данных. Примечание: Судя по комментариям, эти точные команды могут больше не применяться, если вы используете EF Core.

Шаг 1. Восстановите предыдущую миграцию

Если вы еще не применили свою миграцию, вы можете пропустить эту часть. Чтобы восстановить схему базы данных до предыдущей точки, введите команду Update-Database с параметром -TargetMigration, чтобы указать последний удачный перенос. Если код вашей сущностной структуры находится в другом проекте в вашем решении, вам может потребоваться использовать параметр «-Project» или переключить проект по умолчанию в консоли диспетчера пакетов.

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

Чтобы получить имя последней удачной миграции, используйте команду «Get-Migrations», чтобы получить список имен миграции, которые были применены к вашей базе данных.

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

Этот список сначала показывает самые последние примененные миграции. Выберите миграцию, которая происходит в списке после того, на который вы хотите понизить рейтинг, то есть тот, который применен перед тем, на который вы хотите понизить рейтинг. Теперь выполните обновление базы данных.

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

Все миграции, примененные после указанного, будут понижены в порядке, начиная с самой последней, примененной первой.

Шаг 2: Удалить вашу миграцию из проекта

remove-migration name_of_bad_migration

Если remove-migrationкоманда недоступна в вашей версии Entity Framework, удалите файлы нежелательной миграции в папку «Миграции» проекта EF вручную. На этом этапе вы можете создать новую миграцию и применить ее к базе данных.

Шаг 3. Добавьте новую миграцию

add-migration my_new_migration

Шаг 4: применить вашу миграцию к базе данных

update-database
Давид Сопко
источник
6
С EF Core кажется, что Get-Migrations был удален.
Кевин Бертон,
1
Шаг 2 ! - Очень полезная функция. Как упомянул @KevinBurton. А потом add-migration "new migration",update-database
Александр Фролов
2
Update-Database –migration: «<миграция применена до этого>» @David Sopko
Fuat
Спасибо @AlexanderFrolov Я обновил решение, чтобы отразить ваши комментарии.
Давид Сопко
1
нам нужно использовать удаление-миграцию после шага 2
Рахул
56

Для тех, кто использует EF Core с ASP.NET Core v1.0.0, у меня была похожая проблема, и я использовал следующие команды для ее исправления (пост @ DavidSopko указал мне правильное направление, но детали для EF Core немного отличаются) :

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

Например, в моей текущей разработке команда стала

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

Remove-Migration удалит последнюю примененную миграцию. Если вам нужно удалить более сложный сценарий с несколькими миграциями (у меня было только 2, начальный и плохой), я предлагаю вам протестировать шаги в фиктивном проекте.

В настоящее время в EF Core (v1.0.0), по-видимому, нет команды Get-Migrations, поэтому вы должны заглянуть в папку миграции и ознакомиться с тем, что вы сделали. Тем не менее, есть хорошая справочная команда:

PM> get-help entityframework

При обновлении базы данных в VS2015 SQL Server Object Explorer все мои данные были сохранены, и миграция, которую я хотел отменить, исчезла :)

Первоначально я попытался удалить-Migration самостоятельно и нашел команду ошибки смущающей:

System.InvalidOperationException: миграция '...' уже применена к базе данных. Отмените его и попробуйте снова. Если миграция была применена к другим базам данных, рассмотрите возможность возврата ее изменений с помощью новой миграции.

Уже есть предложения по улучшению этой формулировки, но я бы хотел, чтобы ошибка говорила что-то вроде этого:

Запустите Update-Database (последнее правильное имя миграции), чтобы вернуть схему базы данных в это состояние. Эта команда будет отменять все миграции, которые произошли после миграции, указанной в Update-Database. Затем вы можете запустить Remove-Migration (имя миграции для удаления)

Вывод из справочной команды EF Core следующий:

 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
Ричард Логвуд
источник
6

Вы также можете использовать

Remove-Migration -Force

Это вернет и удалит последнюю примененную миграцию

Даниэль Тулп
источник
4

Во-первых, обновите вашу последнюю совершенную миграцию с помощью этой команды:

Update-Database TargetMigration

Пример:

Update-Database -20180906131107_xxxx_xxxx

Затем удалите неиспользованную миграцию вручную.

Абдус Салам Азад
источник
2
это должно быть: Обновление-База данных -TargetMigration 20180906131107_xxxx_xxxx
Elger Mensonides
Update-Database 20180906131107_xxxx_xxxx(без дефиса) работал на меня. Ни одна версия TargetMigrationкак переключатель не работает. Эти команды кажутся движущейся целью (т.е. меняют их в каждой версии)?
Сумма отсутствует
3

Начиная с .NET Core 2.2, TargetMigrationпохоже, уже нет:

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"

Так что это работает для меня сейчас:

Update-Database -Migration 20180906131107_xxxx_xxxx

А также (без -Migrationпереключателя):

Update-Database 20180906131107_xxxx_xxxx

В добавленной заметке вы больше не можете чисто удалять папки миграции, не отключая синхронизацию снимка модели. Так что, если вы усвоите этот трудный путь и в итоге получите пустую миграцию, в которой вы знаете, что должны быть изменения, вы можете запустить (без переключателей, необходимых для последней миграции):

Remove-migration

Это очистит беспорядок и вернет вас туда, где вы должны быть, даже если последняя папка миграции была удалена вручную.

Сумма Нет
источник
0

Для EF 6 вот одна строка, если вы много работаете в процессе разработки. Просто обновите vars и затем продолжайте использовать стрелку вверх в консоли диспетчера пакетов, чтобы промыть и повторить.

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

Почему это необходимо, спросите вы? Не уверен, к каким версиям EF6 это применимо, но если ваша новая цель миграции уже была применена, то использование '-Force' для повторной сборки в Add-Migration фактически не приведет к повторной сборке, но вместо этого создаст новый файл (это хороший вещь, хотя, потому что вы не хотели бы потерять свой «Вниз»). Приведенный выше фрагмент сначала выполняет 'Down', если необходимо, затем -Force работает правильно для повторного создания леса.

madamission
источник