CodeFirst 迁移:如何在 "update-database" 自动完成后 运行 数据库脚本(C# 或 SQL)?

CodeFirst migrations: How to run a database script (C# or SQL) after completion of "update-database" automatically?

我正在使用 EF.Core 和代码优先迁移来更新 SQL 数据库。

每当我添加迁移(包管理器控制台:add-migration)时,我都会使用众所周知的 update-database 命令更新数据库。有没有办法在完成此命令后自动 运行 一个 SQL 批处理脚本(就像你可以在 Visual Studio 中使用 post-build 事件一样)?

该脚本可以备份数据库或执行其他任务(如设置用户角色等)。

我不想修改现有的迁移来执行此操作,我知道您可以添加类似

的内容
   protected override void Up(MigrationBuilder migrationBuilder)
   {
        var sqlFile = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, 
                       @"Migrations200701103006_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

注意:更新数据库运行s在包管理器上下文中,pg_dump运行s在命令shell (cmd.exe) - 因此,您不能 运行 直接在 .cmd 或 .bat 脚本中更新数据库。

我似乎无法在文档中找到任何内容来以您想要的方式执行您想要的操作。

但是,我想到的另一种解决方案是,不是从命令行 运行 将脚本或作为迁移的一部分 class,而是在启动时 运行 它们作为自动迁移的一部分。

所以你可以这样做:

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。不过,请将它们放在不同的文件夹中。

我能想到的两个方案

  1. 更简单:为什么不用一个简单的批处理文件按顺序执行两个命令,然后您可以运行批处理文件而不是Update-Database命令?您甚至可以从标准项目配置文件中获取最多的参数,这样您就可以在多个项目中使用相同的脚本,而无需更改项目配置文件以外的任何内容。通过这种方式,您可以确保您的其他脚本 运行s 在实际需要 Update-Database 命令时响应

  2. 如果这是一个 Powershell 会话,可能以动态方式涉及多个“update-commands”,而您不想使用上述方法,那么您可以尝试订阅 Powershell 引擎Exiting 事件(即 [System.Management.Automation.PsEngineEvent]::Exiting)并在执行 Update-Database 时通过其 -Action 参数自动执行响应脚本(但前提是在同一个 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 会话命令与本地或远程计算机建立持久会话,以便事件订阅者可以考虑在多个文件中执行的命令。

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/