【问题标题】:Entity Framework Migration Azure DevOps Release Pipeline实体框架迁移 Azure DevOps 发布管道
【发布时间】:2020-03-16 03:38:17
【问题描述】:

我正在尝试在 Azure DevOps Release Pipeline 上运行迁移。因为我想在每个版本上自动运行我的数据库脚本。我的发布管道没有源代码,我只是编译了 DLL。

当我在本地机器上执行此命令时,它运行成功。如何转换此命令以便将其与 DLL 一起使用。

dotnet ef database update --project MyEntityFrameworkProject --context MyDbContext --startup-project MyStartupProject

【问题讨论】:

  • 嗨,最近怎么样?下面分享的解决方案呢?考虑接受一个您认为对您有用的答案。

标签: entity-framework azure-devops azure-pipelines entity-framework-migrations azure-pipelines-release-pipeline


【解决方案1】:

另一种方法是在构建管道期间生成迁移脚本(常规 sql 脚本),并使该脚本成为您的工件的一部分。为此,请运行以下命令:

dotnet ef migrations script --output $(build.artifactstagingdirectory)\sql\migrations.sql -i

注意 -i 标志,这使得该脚本可以在同一个数据库上多次运行

将此脚本作为工件的一部分后,您可以使用内置任务Azure SQL Database Deployment 在发布管道中的数据库上运行它。

查看this link了解更多信息

编辑:正如@PartickBorkowicz 指出的那样,从构建/发布代理的角度来看,数据库无法以常规方式使用这一事实存在一些问题。这里有一些额外的提示,如何在没有数据库和连接字符串存储在代码中的任何地方生活。

1.构建管道

如果您什么都不做,构建代理将需要数据库连接才能运行dotnet ef migrations script 脚本。但是有一个技巧可以让你在没有数据库和连接字符串的情况下工作:IDesignTimeDbContextFactory

这样创建类就足够了:

public class YourDesignTimeContextFactory : IDesignTimeDbContextFactory<YourDbContext>
{
    public YourDbContext CreateDbContext(string[] args)
    {
        var databaseConnectionString = "Data Source=(LocalDB)\\MSSQLLocalDB;Initial Catalog=LocalDB;Integrated Security=True;Pooling=False";
        var builder = new DbContextOptionsBuilder<YourDbContext>();
        builder.UseSqlServer(databaseConnectionString);

        return new YourDbContext(builder.Options);
    }
}

一旦它出现在您的项目中(无论如何您都不需要注册它),您的构建代理将能够生成带有迁移逻辑的 sql 脚本,而无需访问实际数据库

2。发布管道

现在,您正在生成 sql 脚本并成为构建管道的工件的一部分。现在,发布管道是您希望此脚本在实际数据库上运行的时间 - 您需要以某种方式连接到此数据库的字符串。要以安全的方式执行此操作,您不应将其存储在代码中的任何位置。一个很好的方法是将密码保存在 Azure Key Vault 中。 Azure 发布管道中有一个名为 Azure Key Vault 的内置任务。这将获取您可以在下一步中使用的秘密:Azure SQL Database Deployment。您只需要设置选项:

AuthenticationType: Connection String
ConnectionString: `$(SqlServer--ConnectionString)` - this value depends on your secret name in Key Vault
Deploy type: SQL Script File
SQL Script: $(System.DefaultWorkingDirectory)/YourProject/drop/migrations/script.sql - this depends how you setup your artifact in build pipeline.

这样,您无需访问数据库即可生成迁移并运行迁移 sql,而无需将连接字符串存储在代码中的任何位置。

【讨论】:

  • 值得注意的是,构建管道代理将需要您的 ef 连接字符串来生成脚本,就像 Add-Migrations 需要它来与数据库对话一样。如果您在源代码中硬编码了连接字符串(例如 appsettings.json),这很好,但如果您将凭据存储在目标服务器上(例如在 Azure 中),则可能会成为问题。
  • @PatrickBorkowicz 这是正确的,但 Azure KeyVault 在这种情况下会派上用场 - 您可以将连接字符串存储在那里并从管道中访问它,而无需将其存储在代码中的任何位置
  • 这是一个了不起的想法;我可以试一试。 Add-Migrations 是一个只读操作(据我所知),因此它在构建时是可以接受的,尽管它确实需要数据库存在并且在线。您甚至可以通过使用访问受限的专用数据库用户/连接字符串来限制其范围。我一直在考虑这种方法。目前,我们使用 context.Database.Migrate() 在运行时(启动时)部署迁移。这很好用,但确实需要重新启动应用程序。
  • @PatrickBorkowicz 检查我的编辑,因为我添加了一些可能很方便的说明
  • @BorisLayvant 的事情是,对于脚本生成,您不需要正确的连接字符串(也不需要数据库)。它仅基于代码中的迁移生成。当您真正想要针对您的数据库运行迁移(脚本)时,您只需要连接字符串(和数据库)。在我的情况下,它是在发布管道(而不是构建管道)中完成的,并且连接字符串是从 KeyVault 获取的
【解决方案2】:

如果您不想在工件中包含源代码,可以使用以下脚本:

set rootDir=$(System.DefaultWorkingDirectory)\WebApp\drop\WebApp.Web
set efPath=C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.entityframeworkcore.tools\2.1.1\tools\netcoreapp2.0\any\ef.dll
dotnet exec --depsfile "%rootDir%\WebApp.deps.json" --additionalprobingpath %USERPROFILE%\.nuget\packages --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" --runtimeconfig "%rootDir%\WebApp.runtimeconfig.json" "%efpath%" database update --verbose --prefix-output --assembly "%rootDir%\AssemblyContainingDbContext.dll" --startup-assembly "%rootDir%\AssemblyContainingStartup.dll" --working-dir "%rootDir%"

事实证明,您可以像以下示例一样使用未记录的 dotnet exec 命令(假设 Web 应用程序称为 WebApp):

请注意,此运行命令行任务的工作目录(隐藏在 Advanced 下)必须设置为工件所在的位置(上面的 rootDir)。

另一种选择是安装 Build & Release Tools 扩展并使用“从 DLL 部署实体框架核心迁移”任务。

您可以阅读更多信息hereherehere

【讨论】:

  • EF6 的任何替代方案?
  • 感谢您的回答,是否可以通过编程方式获取这些文件夹(Nuget Packages、Nuget Fallback 和 EF Dll),因为服务器可以使用不同的操作系统和不同的 EF 核心版本
猜你喜欢
  • 2021-09-22
  • 1970-01-01
  • 2020-02-23
  • 1970-01-01
  • 2021-06-24
  • 1970-01-01
  • 1970-01-01
  • 2015-05-11
相关资源
最近更新 更多