Can't remove Database Migration with Ef Core - entity-framework

Well, I'm trying to revert a database migration that simple add a column, see:
public partial class CreateColumnTypeCamera : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "type",
table: "CAMERA",
type: "varchar",
nullable: false,
defaultValue: "");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "type",
table: "CAMERA");
}
}
After execute dotnet ef database update everything works fine and my database is updated. But I want to revert it, so I tried dotnet ef database update CreateColumnTypeCamera:
[ronaldo#localhost WebApi]$ dotnet ef database update CreateColumnTypeCamera
Done.
As you can see I got "Done", but nothing is reverted, the column was not dropped. If I try to remove my migration I got an error:
[ronaldo#localhost WebApi]$ dotnet ef migrations remove
The migration '20200329134024_CreateColumnTypeCamera' has already been applied to the database. Revert it and try again. If the migration has been applied to other databases, consider reverting its changes using a new migration.
Edit 1:
I applied the "update" command to "LastGoodMigration" instead my bad migration, and everything works fine. But the error in remove continue, so I noted that is because of this line:
if (Database.ProviderName != "Microsoft.EntityFrameworkCore.InMemory")
{
Database.Migrate();
}
There is any way to fix it ? If I try to apply "ef remove" with this line I got the error showed above.

You will need to run
update-database OneMigrationBeforeTheOneYouWantToRemove
Updating database to the previous migration of the one you want to remove. This will revert changes on the database and also remove the migration from _migrations table.
After that you can run:
Remove-Migration
which will remove the last migration, you can run it 'n' times until you reach the desire migration to remove.

go to database, table EF_migrations and remove the migration with specific id (table row), then you can remove the files from migrations folder. Don't forgot to update manually the tables which are affected by this migration.

Related

How to Cleanup & generate fresh migration for existing DB?

We wish to get rid of 100s of migration classes as DB schema in production is final.
Here are the steps I followed:
Delete Migrations folder.
Add-Migration -??
What command line switches, could help us?
EDIT:
If all goes well Up() method of migration should be empty right? For
example following is wrong generation on Add-Migration. Because if we
execute the project we will get duplicate table errors.
public partial class Sanity : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.AccountPreferences",
c => new
{
AccountID = c.Guid(nullable: false),
}
.... for 1000s of tables
}
}
A clean migration would be something: when trying Add-Migration on subsequent changes, should not be getting any error.
Unable to generate an explicit migration because the following
explicit migrations are pending: [201712281054591_Sanity]. Apply the
pending explicit migrations before attempting to generate a new
explicit migration.
As you can see if we happen to execute Update-Database will get table already exist error.
Are we forced to always retains all migration copies?
See if this can help:
MVC3 and Code First Migrations - "model backing the 'blah' context has changed since the database was created"
Entity framework code first - how to run Update-Database for production database
How to delete and recreate from scratch an existing EF Code First database
note:
I'm writing this from memory, if you have issues let me know and I'll recheck exactly.
Also, my knowledge on this is from slightly older versions of EF as I haven't done much work there recently, but I doubt much has changed.
From what I can tell, if you want to...
a) keep the db,
b) clean your project migrations,
c) have the 2 'match', be in sync:
do the following:
- Remove the migration folder (your project)
- Run Add-Migration Initial - then should add one migration
- caution: it is safe but do backup, change connection string etc. before the next step
- Run Update-Database -Script - that doesn't update the db but creates the SQL script, including the migration table
- find the INSERT INTO [__MigrationHistory] records, just run those (on your db), insert them into the database
...then test with Add-Migration again, to see if it is going to make anything, should yield no new migrations, empty one.
Please read through the first link above and adjust approach as needed.
I'm sure there might be easier, shorter ways to do this (via PM console) but unaware of it at the moment.
Open your database.
Clear table __MigrationHistory
Remove migrations in the folder
Run Add-Migration MigrationName
Almost the same as accepted one, but no scripting the initial migration.
Drop the __MigrationHistory db table
Remove all the migration files in the Migrations folder
Run Add-migration Initial in Package Manager Console
Comment out the code inside of the Up method in the Initial Migration
Run Update-database in PM Console (just to create a Migration Entry)
Remove comments in the Initial migration
Wonder how long it will be "final" ?
Use:
Add-Migration Initial
After removing the migrations folders

Why can I only enable code migrations if also enable automatic code migrations?

There was a breaking change so we decided to reset migrations, but now If we don't put the -EnableAutomaticMigrations option Enable-Migrations doesn't work.
My connection string is in my web project that is set as the startup project.
This are the steps we took:
First We deleted the Migrations folder and the database completely.
Then When we do:
enable-migrations
We get:
Checking if the context targets an existing database...
Unable to update database to match the current model because there are pending
changes and automatic migration is disabled. Either write the pending
model changes to a code-based migration or enable automatic migration.
Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to
enable automatic migration.
I don't understand this error, there is no database, there are no migrations, to what pending changes does it refer to? (I dont even have pending chanves in git)
If then We do
enable-migrations -EnableAutomaticMigrations
It works, but when We follow it with:
Add-Migration InitialCreation
It creates an Empty InitialCreation migration and it creates the database with the tables that correspond to my model. But doing this We can't get the scripts for creating the database for the first time. I don't get what is going on.
It seems the first time it uses some Automatic migration.
Why can't We enable-migrations without -EnableAutomaticMigrations?
Update
After talking with Steve Green, I think it could be useful to add part of my DbContext and Initializer
public class ApplicationDatabaseContext : DbContext
{
public ApplicationDatabaseContext()
: base("MyConnectionStringName")
{
Database.SetInitializer<ApplicationDatabaseContext>(new ApplicationDataInitializer());
if (!Database.Exists())
{
Database.Initialize(true);
}
}
And my DatabaseInitializer:
public class ApplicationDataInitializer : CreateDatabaseIfNotExists<ApplicationDatabaseContext>
{
protected override void Seed(ApplicationDatabaseContext context)
{
base.Seed(context);
CreateData(context);
}
private void CreateData(ApplicationDatabaseContext context)
{
//Add data here
context.SaveChanges();
}
}
First, make sure you have the initializer MigrateDatabaseToLatestVersion set.
Second, You should not need to enable automatic migrations. To reset migrations you don't have to delete the entire folder (especially if you've done some seeding or other customizations in the Configuration() class). Just delete the individual migrations then add a new baseline migration:
add-migration MyStartPoint -IgnoreChanges
This will take a snapshot with no code in the Up() since you don't really need that to generate a script to create the database. So now update-database -Script -SourceMigration $InitialDatabase should create a script you can use to create a new database.
Another option is to use an initializer like CreateDatabaseIfNotExist which will do exactly that.

Entitfy Framework: everything is broken when I change schema

I use EF with code-first approach.
I have a class:
public class Cat {
// ...
}
Then I add some properties and migrations for them. So I have a couple of existing migrations. Then I create abstract class:
public abstract class Animal {
// ...
}
And inherit a Cat from Animal:
public Cat : Animal {
// ...
}
When I do that, and run add-migration I run into the problem I can't solve. EF gives me an error:
Unable to generate an explicit migration because the following
explicit migrations are pending: [...]. Apply the pending explicit
migrations before attempting to generate a new explicit migration.
This is because schema is stored in __MigrationHistory. And when EF tries to compare the current schema with schema fetched from database (from __MigrationHistory), it fails.
Everything's fine when I drop all of Migrations and create the database from scratch.
But I don't want to drop the entire database when schema changes.
How can I handle schema changes with EF?
Here is similar post, but without any good solution.
If you ran Add-Migration and didn't run Update-Database then run it.
But some times you run following command:
PM>add-migration migration1
Then make some changes to your model, in this case if you want to add another migration, you get mentioned error, so you have 2 options:
Run Update-Database to apply pending changes of migration1 to database and then add new migration.
Run add-migration migration1 -force to add all pending migrations as migration1 and then run update-database.
Try running Update-Database before you run Add-Migration

Should we need to add explicit db migrations when using MigrateDatabaseToLatestVersion?

Recently I have faced issue with EF codefirst DB migrations. We have used MigrateDatabaseToLatestVersion for DB initializer.
Database.SetInitializer(new MigrateDatabaseToLatestVersion<TestDataContext, MyConfiguration>());
internal sealed class MyConfiguration : DbMigrationsConfiguration<TestDataContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
...
Issue is that - we accidentally ran old DB migration file using the below command :
Update-database -TargetMigration some_old_test_migration_cs_file
This caused us to loose latest entity schema changes and we were unable to push latest changes to database. After wasting a lot of time in troubleshoot, we fixed that issue by deleting migration history from the table __MigrationHistory.
My question is - Should we also add migration scripts whenever entity (code level) changes though we have enabled the automatic migrations?
What would be the best practice around this?
If you're using Automatic Migrations, you shouldn't need to code any explicit migrations yourself. Entity Framework will automatically update the database to match the current state of your entities when you create a context.

Resetting EF Code-First Migration State

I'm using EF 5. We are looking to convert our project to use code-first migrations.
Originally in our DBContext file we had an IDataBaseInitializer implementation that creates the DB if it doesn't exist (using context.Database.Create).
I wanted to test out the migration concept so I originally ran the commands:
Enable-Migrations -ProjectName MyProjectName
(This successfully created a Migrations folder with a Configuration.cs file)
Add-Migration Initial -ProjectName MyProjectName
(This successfully created a script file which matched my model classes)
At this point I wanted to try testing upgrade scenario so I created a tmp field on my model and reran the Add-Migration command which seemed to work as expected.
However at this point I wanted to reset my state. I've reverted all my changes in VS, removed the files from the Migrations folder from disk, tried removing the __MigrationsHistory table from my DB (and also completely deleting the DB). No matter what I do I can't get a new Add-Migration to create a script that includes my initial state. It always appears as this... this is my test value that I created originally.
public partial class Initial : DbMigration
{
public override void Up()
{
DropColumn("dbo.EventTrackingRecords", "TestValue");
}
public override void Down()
{
AddColumn("dbo.EventTrackingRecords", "TestValue", c => c.String());
}
}
I don't understand where it's keeping this initial information. The only other thing that I found interesting is that if I run my program after deleting the DB, it recreates my DB as I would expect based on the model, but it also creates a __MigrationHistory table! I don't understand how the context.Database.Create() command is doing this.
EF creates the __MigrationHistory table to keep your DB up to date, and warn you if it's not.
When you edit something in your models, and run the add-migration, you have to run update-database to be able to create a new migration. EF won't allow you to have pending migrations while creating new ones.
So, if you add a property to one of your models, and then create a migration, you have to update the database before creating a new migration where you delete the property.
Hope this helps.