[c#] Entity Framework rollback and remove bad migration

I'm using EF 6.0 for my project in C# with manual migrations and updates. I have about 5 migrations on the database, but I realised that the last migration was bad and I don't want it. I know that I can rollback to a previous migration, but when I add a new (fixed) migration and run Update-Database, even the bad migration is applied.

I was trying to rollback to the previous migration and delete the file with bad migration. But then, when I try to add new migration, I get error when updating database, because the migration file is corrupted (more specifically, first line of code rename the table A to B and is next lines, EF is trying to update table with name A - maybe it is some EF bug).

Is there some query I can run, which would tell EF something like "Forget last migration like it never existed, it was bad"? Something like Remove-Migration.

Edit1 I found solution suited for me. Changing model to the good state and run Add-Migration TheBadMigration -Force. This will re-scaffold the last, not applied migration.

Anyway, this still not answer the original question completely. If I UpdateDatabase to the bad migration, I did not found good way how to rollback and create new migration, excluding the bad one.

Thanks

This question is related to c# entity-framework migration rollback

The answer is


I am using EF Core with ASP.NET Core V2.2.6. @Richard Logwood's answer was great and it solved my problem, but I needed a different syntax.

So, For those using EF Core with ASP.NET Core V2.2.6 +...

instead of

Update-Database <Name of last good migration>

I had to use:

dotnet ef database update <Name of last good migration>

And instead of

Remove-Migration

I had to use:

dotnet ef migrations remove

For --help i had to use :

dotnet ef migrations --help


Usage: dotnet ef migrations [options] [command]

Options:
  -h|--help        Show help information
  -v|--verbose     Show verbose output.
  --no-color       Don't colorize output.
  --prefix-output  Prefix output with level.

Commands:
  add     Adds a new migration.
  list    Lists available migrations.
  remove  Removes the last migration.
  script  Generates a SQL script from migrations.

Use "migrations [command] --help" for more information about a command.

This let me role back to the stage where my DB worked as expected, and start from beginning.


For EF 6 here's a one-liner if you're re-scaffolding a lot in development. Just update the vars and then keep using the up arrow in package manager console to rinse and repeat.

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

Why is this necessary you ask? Not sure which versions of EF6 this applies but if your new migration target has already been applied then using '-Force' to re-scaffold in Add-Migration will not actually re-scaffold, but instead make a new file (this is a good thing though because you wouldn't want to lose your 'Down'). The above snippet does the 'Down' first if necessary then -Force works properly to re-scaffold.


As of .NET Core 2.2, TargetMigration seems to be gone:

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"

So this works for me now:

Update-Database -Migration 20180906131107_xxxx_xxxx

As well as (no -Migration switch):

Update-Database 20180906131107_xxxx_xxxx

On an added note, you can no longer cleanly delete migration folders without putting your Model Snapshot out of sync. So if you learn this the hard way and wind up with an empty migration where you know there should be changes, you can run (no switches needed for the last migration):

Remove-migration

It will clean up the mess and put you back where you need to be, even though the last migration folder was deleted manually.


First, Update your last perfect migration via this command :

Update-Database –TargetMigration

Example:

Update-Database -20180906131107_xxxx_xxxx

And, then delete your unused migration manually.


You can also use

Remove-Migration -Force

This will revert and remove the last applied migration


As the question indicates this applies to a migration in a development type environment that has not yet been released.

This issue can be solved in these steps: restore your database to the last good migration, delete the bad migration from your Entity Framework project, generate a new migration and apply it to the database. Note: Judging from the comments these exact commands may no longer be applicable if you are using EF Core.

Step 1: Restore to a previous migration

If you haven't yet applied your migration you can skip this part. To restore your database schema to a previous point issue the Update-Database command with -TargetMigration option specify the last good migration. If your entity framework code resides in a different project in your solution, you may need to use the '-Project' option or switch the default project in the package manager console.

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

To get the name of the last good migration use the 'Get-Migrations' command to retrieve a list of the migration names that have been applied to your database.

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

This list shows the most recent applied migrations first. Pick the migration that occurs in the list after the one you want to downgrade to, ie the one applied before the one you want to downgrade. Now issue an Update-Database.

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

All migrations applied after the one specified will be down-graded in order starting with the latest migration applied first.

Step 2: Delete your migration from the project

remove-migration name_of_bad_migration

If the remove-migration command is not available in your version of Entity Framework, delete the files of the unwanted migration your EF project 'Migrations' folder manually. At this point, you are free to create a new migration and apply it to the database.

Step 3: Add your new migration

add-migration my_new_migration

Step 4: Apply your migration to the database

update-database

For those using EF Core with ASP.NET Core v1.0.0 I had a similar problem and used the following commands to correct it (@DavidSopko's post pointed me in the right direction, but the details are slightly different for EF Core):

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

For example, in my current development the command became

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

The Remove-Migration will remove the last migration you applied. If you have a more complex scenario with multiple migrations to remove (I only had 2, the initial and the bad one), I suggest you test the steps in a dummy project.

There doesn't currently appear to be a Get-Migrations command in EF Core (v1.0.0) so you must look in your migrations folder and be familiar with what you have done. However, there is a nice help command:

PM> get-help entityframework

Refreshing dastabase in VS2015 SQL Server Object Explorer, all of my data was preserved and the migration that I wanted to revert was gone :)

Initially I tried Remove-Migration by itself and found the error command confusing:

System.InvalidOperationException: The migration '...' has already been applied to the database. Unapply it and try again. If the migration has been applied to other databases, consider reverting its changes using a new migration.

There are already suggestions on improving this wording, but I'd like the error to say something like this:

Run Update-Database (last good migration name) to revert the database schema back to to that state. This command will unapply all migrations that occurred after the migration specified to Update-Database. You may then run Remove-Migration (migration name to remove)

Output from the EF Core help command follows:

 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

You have 2 options:

  • You can take the Down from the bad migration and put it in a new migration (you will also need to make the subsequent changes to the model). This is effectively rolling up to a better version.

    I use this option on things that have gone to multiple environments.

  • The other option is to actually run Update-Database –TargetMigration: TheLastGoodMigration against your deployed database and then delete the migration from your solution. This is kinda the hulk smash alternative and requires this to be performed against any database deployed with the bad version.

    Note: to rescaffold the migration you can use Add-Migration [existingname] -Force. This will however overwrite your existing migration, so be sure to do this only if you have removed the existing migration from the database. This does the same thing as deleting the existing migration file and running add-migration

    I use this option while developing.


Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to entity-framework

Entity Framework Core: A second operation started on this context before a previous operation completed EF Core add-migration Build Failed Entity Framework Core add unique constraint code-first 'No database provider has been configured for this DbContext' on SignInManager.PasswordSignInAsync The instance of entity type cannot be tracked because another instance of this type with the same key is already being tracked Auto-increment on partial primary key with Entity Framework Core Working with SQL views in Entity Framework Core How can I make my string property nullable? Lazy Loading vs Eager Loading How to add/update child entities when updating a parent entity in EF

Examples related to migration

Want to upgrade project from Angular v5 to Angular v6 Laravel 5.4 Specific Table Migration SQLSTATE[HY000] [2002] Connection refused within Laravel homestead Laravel migration table field's type change How can I rename column in laravel using migration? Warning about `$HTTP_RAW_POST_DATA` being deprecated Entity Framework rollback and remove bad migration Migration: Cannot add foreign key constraint Maven is not working in Java 8 when Javadoc tags are incomplete Rails: Adding an index after adding column

Examples related to rollback

Entity Framework rollback and remove bad migration How to discard all changes made to a branch? How do I view an older version of an SVN file? How to rollback a specific migration? How can I undo a mysql statement that I just executed? How can I roll back my last delete command in MySQL? How can I rollback an UPDATE query in SQL server 2005?