Применение миграций


Применение миграции во время выполнения

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

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

Чтобы программно применить миграции, вызовите context.Database.Migrate() . например, типичное ASP.NET приложение может выполнять следующие действия:

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    using (var scope = host.Services.CreateScope())
    {
        var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
        db.Database.Migrate();
    }

    host.Run();
}

Обратите внимание, что Migrate() строится на основе IMigrator службы, которую можно использовать для более сложных сценариев. Для доступа к нему используйте myDbContext.GetInfrastructure().GetService<IMigrator>().

Предупреждение

  • Перед использованием этого подхода в рабочей среде тщательно обсудите этот подход. Опыт показал, что простота этой стратегии развертывания определяется проблемами, которые она создает. вместо этого рекомендуется создавать скрипты SQL.
  • Не вызывайте EnsureCreated() перед Migrate(). EnsureCreated() обходит миграции, чтобы создать схему, что приводит к сбою Migrate().

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

Примечание

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

Скрипты SQL

рекомендуемый способ развертывания миграций в рабочей базе данных — создание сценариев SQL. Ниже перечислены преимущества этой стратегии.

  • SQL сценарии могут быть проверены на точность; это важно, поскольку применение изменений схемы к рабочим базам данных является потенциально опасной операцией, которая может привести к потере данных.
  • В некоторых случаях сценарии могут быть настроены в соответствии с конкретными потребностями рабочей базы данных.
  • SQL скрипты можно использовать в сочетании с технологией развертывания, и даже в рамках процесса CI.
  • SQL сценарии могут быть предоставлены администратору баз данных, и их можно управлять и архивировать отдельно.

Основное использование

следующий сценарий создает SQL скрипт из пустой базы данных для последней миграции:

dotnet ef migrations script

С from (в подразумеваемую миграцию)

в следующем примере создается скрипт SQL из данной миграции в последнюю миграцию.

dotnet ef migrations script AddNewTables

С from и to

в следующем примере создается скрипт SQL из указанной from миграции в указанную to миграцию.

dotnet ef migrations script AddNewTables AddAuditTable

Для создания скрипта отката можно использовать значение from, более новое, чем to.

Предупреждение

Обязательно учитывайте возможные сценарии потери данных.

Создание скрипта принимает следующие два аргумента, указывающие, какой диапазон миграций должен быть создан:

  • Миграция from должна быть последней миграцией, применяемой к базе данных перед выполнением скрипта. Если не было применено ни одной миграции, укажите 0 (это значение по умолчанию).
  • Миграция to является последней миграцией, применяемой к базе данных после выполнения скрипта. По умолчанию она является последней миграцией в проекте.

идемпотентными сценарии SQL

описанные выше сценарии SQL могут быть применены только для изменения схемы с одной миграции на другую; вы обязаны правильно применять сценарий и только к базам данных в правильном состоянии миграции. EF Core также поддерживает создание сценариев идемпотентными , которые внутренне проверяют, какие миграции уже применены (с помощью таблицы журнала миграции), и применяют только недостающие. Это полезно, если вы не точно понимаете, какая последняя миграция была применена к базе данных, или если вы развертываете несколько баз данных, которые могут быть в разных переносах.

Ниже приводится пример идемпотентными миграций.

dotnet ef migrations script --idempotent

Средства командной строки

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

  • SQL команды применяются непосредственно средством, не давая разработчику возможность их исследовать или изменять. Это может быть опасно в рабочей среде.
  • Пакет SDK для .NET и средство EF должны быть установлены на рабочих серверах и требуют исходного кода проекта.

В следующем примере база данных обновляется до последней миграции:

dotnet ef database update

Следующий пример обновляет базу данных на заданную миграцию:

dotnet ef database update AddNewTables

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

Предупреждение

Обязательно учитывайте возможные сценарии потери данных.

Дополнительные сведения о применении миграций с помощью программ командной строки см. в справочнике по инструментам EF Core.

Пакеты

Примечание

Эта функция появилась в EF Core 6,0.

Пакеты миграции — это исполняемые файлы с одним файлом, которые можно использовать для применения миграций к базе данных. они устраняют некоторые недостатки SQL сценария и программ командной строки:

  • для исполнения сценариев SQL требуются дополнительные средства.
  • Обработка транзакций и поведение "продолжение при ошибке" для этих средств являются непоследовательными и иногда непредвиденными. Это может привести к неопределенному состоянию базы данных, если при применении миграции произойдет сбой.
  • Пакеты можно создавать в рамках процесса непрерывной интеграции и легко выполнять позднее в рамках процесса развертывания.
  • Пакеты могут выполняться без установки пакета SDK .NET или EF (или даже среды выполнения .NET, если они находятся в автономном виде) и не нуждаются в исходном коде проекта.

В следующем примере создается пакет:

dotnet ef migrations bundle

В следующем примере создается автономный пакет для Linux:

dotnet ef migrations bundle --self-contained -r linux-x64

Дополнительные сведения о создании пакетов см. в справочнике по инструментам EF Core.

efbundle

Результирующий исполняемый файл efbundle по умолчанию имеет имя. Его можно использовать для обновления базы данных до последней миграции. Он эквивалентен запуску dotnet ef database update или Update-Database .

Аргументы:

Аргумент Описание
<MIGRATION> Целевая миграция. Если значение равно "0", все миграции будут отменены. По умолчанию используется последняя миграция.

Параметры:

Параметр Short Описание
--connection <CONNECTION> Строка подключения к базе данных. По умолчанию используется значение, указанное в AddDbContext или onconfiguring.
--verbose -v Отображение подробных выходных данных.
--no-color Не замечайте выходные данные.
--prefix-output Вывод префикса с уровнем.

следующий пример применяет миграцию к локальному экземпляру SQL Server, используя указанные имя пользователя и пароль.

.\efbundle.exe --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;User ID=myUsername;Password=myPassword'