Хорошо, с тех пор как я задал этот вопрос, я довольно много экспериментировал с этим.
На данный момент, кажется, лучший способ сделать это - вариант 1. Вариант 2 был бы намного лучше, но до тех пор, пока эта функция EFCore не будет реализована, это не очень возможно для моего варианта использования (поддержка существующих БД с миграциями на них и поддерживающие пустые БД).
Вариант 1 также имеет несколько ловушек, на которые я наткнулся (возможно, даже больше, на которые я не наткнулся).
Вот как я это сделал:
Создать новую начальную миграцию:
- Убедитесь, что все ваши существующие миграции были применены к вашей базе данных. Мы создадим новую начальную миграцию, поэтому миграции, которые не были применены, будут потеряны.
- Удалите старые файлы миграции EFCore и файл снимка базы данных.
- Создать новую начальную миграцию из текущего состояния вашей базы данных. (Например, через
dotnet ef migrations add Initial-PostCleanup
.)
Эта новая миграция совместима только с новыми базами данных, так как она создаст все таблицы (и потерпит неудачу, если какие-либо таблицы, ограничения и т. Д. Уже существуют). Итак, теперь мы собираемся сделать эту миграцию совместимой с существующей базой данных:
- Создайте сценарий SQL для новой начальной миграции с помощью
dotnet ef migrations script -o script.sql
.
- Удалить первую транзакцию (до первой
GO
), которая создает таблицу __EFMigrationsHistory
:
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
- Удалить последнюю транзакцию, которая вставляет новую запись в таблицу
__EFMigrationsHistory
:
INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
VALUES (N'20190704144924_Initial-PostCleanup', N'2.2.4-servicing-10062');
GO
- Удалить
GO
команды, так как мы поместим скрипт create в оператор IF:
Заменить GO\r\n\r\n
ничем.
- Теперь откройте файл миграции (файл C #, а не файл sql) и замените метод
Up
следующим:
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
");
}
Готово! Все должно работать сейчас!
Обязательно сравните схему базы данных и данные до и после для новой базы данных. Все, что не является частью, если ваша модель EF Code не является частью новой базы данных.