Recommended way to clean old Entity Framework Core migrations
A bit late, but we had the same problem in our current project. Above 400 migraitons and 6m lines of code inside .Designer. Here is how we managed to resolve this problem:
MigrationProject.csproj
<PropertyGroup>
...
<DefaultItemExcludes Condition="'$(Configuration)' == 'Debug' ">$(DefaultItemExcludes);Migrations\**\*.Designer.cs</DefaultItemExcludes>
</PropertyGroup>
This way you don't need to reset migrations to a clear state neither delete .Designer files. You can always change configuration to Release and use .Designer files by any means necessary.
Okay, since asking this question I've experimented quite a bit with this.
It seems for now, the best way to accomplish this is option 1. Option 2 would be much better, but until this EFCore feature is implemented, it's not really doable for my use case (supporting existing dbs with migrations on them, and supporting empty dbs).
Option 1 also has a few pitfalls which I stumbled upon (maybe even more that I haven't stumbled upon). So this is how I did it:
Create a new initial migration:
- Make sure all your existing migrations have been applied to your database. We'll create a new initial migration, so the migrations that haven't been applied will be lost.
- Delete your old EFCore migration files, and the database snapshot file.
- Create a new Initial migration from your database's current state. (For example via
dotnet ef migrations add Initial-PostCleanup
.)
This new migration is only compatible with new databases, since it will create all tables (and fail if any of the tables, constraints, etc. already exist). So now we're going to make this migration compatible with the existing database:
- Create a SQL script for the new initial migration via
dotnet ef migrations script -o script.sql
. - Remove the first transaction (until the first
GO
), which creates the__EFMigrationsHistory
table:
IF OBJECT_ID(N'[__EFMigrationsHistory]') IS NULL
BEGIN
CREATE TABLE [__EFMigrationsHistory] (
[MigrationId] nvarchar(150) NOT NULL,
[ProductVersion] nvarchar(32) NOT NULL,
CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId])
);
END;
GO
- Remove the last transaction, that inserts the new entry in the
__EFMigrationsHistory
table:
INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20190704144924_Initial-PostCleanup', N'2.2.4-servicing-10062');
GO
- Remove
GO
commands, since we will put the create script in an IF statement:
ReplaceGO\r\n\r\n
with nothing. - Now open up your migration file (the C# file, not the sql file) and replace the
Up
method with the following:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(@"
DECLARE @migrationsCount INT = (SELECT COUNT(*) FROM [dbo].[__EFMigrationsHistory])
IF @migrationsCount = 0
BEGIN
% PASTE YOUR EDITED SQL SCRIPT HERE %
END
");
}
Done! Everything should work now!
Be sure to compare the database schema, and data before and after for the new database. Everything that's not part if your EF Code model is not part of the new database.