CodeFirst миграции: как запустить сценарий базы данных (C# или SQL) после автоматического завершения «update-database»? - PullRequest
1 голос
/ 13 июля 2020

Я использую EF.Core с миграциями с первым кодом для обновления базы данных SQL.

Каждый раз, когда я добавляю миграции (Консоль диспетчера пакетов: add-migration), я обновляю базу данных с помощью хорошо -известная update-database команда. Есть ли способ запустить пакетный сценарий SQL после автоматического завершения этой команды (как вы можете сделать с событиями после сборки в Visual Studio)?

Этот сценарий может создавать резервные копии базы данных или выполнять другие задачи ( например, установка ролей пользователей и т. д. c).

Я не хочу изменять существующие миграции для этого, я знаю, что вы можете добавить что-то вроде

   protected override void Up(MigrationBuilder migrationBuilder)
   {
        var sqlFile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, 
                       @"Migrations\20200701103006_MySQLBatch_Up.sql");
        var sqlCommands = System.IO.File.ReadAllText(sqlFile);
        migrationBuilder.Sql(sqlCommands);

        // ...
   }

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

Есть ли событие или метод, которые можно переопределить для достижения Это? Или что-то, что может быть запущено, например скрипт?

Фактически, я хочу добиться, чтобы скрипт или метод вызывали:

update-database
pg_dump -h localhost -U postgres -p 5432 myDatabase > C:\Temp\myDatabase.sql

Примечание: update-database запускается в контексте диспетчера пакетов, pg_dump запускается в командной оболочке (cmd.exe) - следовательно, вы не можете напрямую запустить update-database в сценарии .cmd или .bat. .

Ответы [ 2 ]

3 голосов
/ 05 августа 2020

Два варианта, которые я могу придумать

  1. Проще: почему бы не иметь простой пакетный файл, который выполняет обе команды последовательно, а затем вы можете запустить пакетный файл вместо Update-Database команда? Вы даже можете получить большинство параметров из стандартного файла конфигурации проекта, и таким образом вы можете использовать один и тот же сценарий в нескольких проектах, не изменяя ничего, кроме файла конфигурации проекта. Таким образом, вы убедитесь, что ваши дополнительные скрипты запускаются в ответ на команду Update-Database, когда она действительно предназначена

  2. Если это для сеанса Powershell, который может включать несколько «команд обновления» в динамическим c способом, и вам не нужен вышеуказанный подход, тогда вы можете попробовать подписаться на событие Powershell Engine Exiting (т.е. [System.Management.Automation.PsEngineEvent]::Exiting) и автоматически выполнить сценарий в ответ через его параметр -Action в любое время Update-Database выполняется (но только в том же Powershell сеансе ).

См. подробности и примеры в команде Register-EngineEvent

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/register-engineevent?view=powershell-7

Внутри вашего сценария действия вы можете получить сведения о событии (например, $Events[0].MessageData) и найти текст " Database-Update ", а затем выполнить желаемые команды в ответ. Это может стать ошибочным, если текст " Database-Update " появляется в любом непредусмотренном контексте сеанса.

Вы можете просмотреть подробные сведения о команде Get-Event и примеры здесь

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-event?view=powershell-7

Вы можете настроить постоянный сеанс с локальным или удаленным компьютером с помощью команды New-PSSession session, чтобы подписчик событий мог учитывать команды, выполняемые в нескольких файлах.

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/new-pssession?view=powershell-7

Подробнее о различных типах сеансов Powershell

https://www.sconstantinou.com/windows-powershell-sessions-pssessions/

2 голосов
/ 03 августа 2020

Кажется, я не могу найти в документации ничего, что могло бы делать то, что вы хотите, так, как вы хотите.

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

Таким образом, вы можете сделать что-то вроде этого:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext dataContext)
{
    // migrate changes on startup
    dataContext.Database.Migrate();
    foreach(var file in GetMigrationFiles())//you can write the code that searches a folder for SQL scripts to execute
    {       
       dataContext.Database.ExecuteSqlRaw(File.ReadAllText(file));
    }
}

Убедитесь, что закажите ваш GetMigrationFiles () правильно.

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

...