3

具有 CLR dll 的数据库已从 SQL Server 2008R2 迁移到 SQL Server 2017。
使用 Azure DevOps 中的 DacPac 自动部署到此数据库。

该 dll 注册于EXTERNAL_ACCESS.

由于迁移到新服务器,部署管道中断。

这是我到目前为止所做的修复它。

  1. 我将数据库项目中的目标平台从 SQL Server 2008 更改为 SQL Server 2017。

    管道中的错误从

    无法连接到主服务器或目标服务器。您必须在主服务器或目标服务器中拥有具有相同密码的用户

    内部错误。Microsoft.Data.Tools.Schema.Sql.Sql140DatabaseSchemaProvider 类型的数据库平台服务无效。您必须确保服务已加载,或者您必须提供有效数据库平台服务的完整类型名称。

  2. 根据这个答案,Microsoft SQL Server Data-Tier Application Framework (17.1 DacFx) 安装在构建代理上。

    管道中的错误更改为

    程序集“system.componentmodel.dataannotations,版本=3.5.0.0,文化=中性,publickeytoken=31bf3856ad364e35。” 在 SQL 目录中找不到。

  3. 然后我将数据库项目中 dll 的目标框架从 NET Framework 3.5 更改为 NET Framework 4.0

    管道中的错误更改为:

    无法部署包。错误 SQL72014:.Net SqlClient 数据提供程序:消息 6218,级别 16,状态 2,第 1 行为
    程序集“System.ComponentModel.DataAnnotations”创建程序集失败,因为程序集“System.ComponentModel.DataAnnotations”验证失败。
    检查引用的程序集是否是最新的并且受信任(对于 external_access 或不安全)以在数据库中执行。
    如果有任何 CLR 验证器错误消息将跟随此消息

    [ : System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptionProvider::GetTypeDescriptor][mdToken=0x6000003][offset 0x00000000] 代码大小为零。
    [ : System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptionProvider::.ctor][mdToken=0x6000001][offset 0x00000000] 代码大小为零。
    [ : System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptionProvider::.ctor][mdToken=0x6000002][offset 0x00000000] 代码大小为零。
    [ : System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptor::GetAttributes][mdToken=0x6000007][offset 0x00000000] 代码大小为零。
    [ : System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptor::GetProperties][mdToken=0x6000006][offset 0x00000000] 代码大小为零。
    [ : System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptor::GetProperties][mdToken=0x6000005][offset 0x00000000] 代码大小为零。
    [ : System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptor::.ctor][mdToken=0x6000004][offset 0x00000000] 代码大小为零。
    [ : System.ComponentModel.DataAnnotations.AssociationAttribute::.ctor][mdToken=0x6000008][offset 0x00000000] 代码大小为零。
    [ : System.ComponentModel.DataAnnotations.AssociationAttribute::get_Name][mdToken=0x6000009][offset 0x00000000] 代码大小为零。
    [ : System.ComponentModel.DataAnnotations.AssociationAttribute::get_ThisKey][mdToken=0x600000a][offset 0x00000000] 代码大小为零。
    [ : System.ComponentModel.DataAnnotations.AssociationAttribute::get_OtherKey][mdToken=0x600000b][offset 0x00000000] 代码大小为零。
    [:System.ComponentModel.DataAnnotations.AssociationAttribute::get_IsForeignKey][mdToken=0x60000 ...

    错误 SQL72045:脚本执行错误。执行的脚本: CREATE ASSEMBLY [System.ComponentModel.DataAnnotations] 授权 [dbo] 来自0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C010300B7E0A14B0000000000000000E00022200B01080000B00000000800000000000092CF00000020000000E000000000C4600020000000020000040000000000000004000000000000000020010000020000CBF4000003004085000010000010000000001000001000000000000010000000000000000000000040CF00004F00000000E00000E0040000000000000000000000BA000088170000000001000C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E7465787400000098AF00000020000000B0000000020000000000000000000000000000200000602E72737263000000E004000000E000000006000000B20000000000000000000000000000400000402E72656C6F6300000C0

从第 3 步开始,我一直无法进步。我从那里开始的所有尝试都没有做任何事情。这是我尝试过的。

  • 将外部访问权限授予 [userName]
  • 将不安全的程序集授予用户名]
  • ALTER DATABASE [DatabaseName] 设置可信
  • SET [userName] 作为 db_owner
    SET [userName] 作为 sysadmin
  • 将 dll 的所有依赖项设置为 UNSAFE
  • 将“启用 clr”设置为 1
  • 将“clr 严格安全”设置为 0
  • 成功导入了一个虚拟 CLR DLL
  • 我已经用一个简单的虚拟项目复制了这个问题,该项目引用了激活System.ComponentModel.DataAnnotations的属性。Model Aware

接下来我可以做什么来修复 DacPac 部署?

编辑 :

我的下一个尝试是反编译System.ComponentModel.DataAnnotations,看看使用我自己的版本的管道是否会更顺畅。我尝试这样做是因为,我在某处读到服务器验证 dll 是否已存在于 GAC 中。如果是这样,那么 dll 版本/签名非常匹配。因此,我觉得即使我设法加载了这个程序集,在其他服务器维护之后它也必然会再次失败。因此,使用这个 dll 的成本与收益是很糟糕的。知道了,反正也只用到了一小部分的dll,还不如把反编译器里用到的代码拿来。

4

1 回答 1

3

看起来您受到clr strict security的影响,以确认它尝试手动部署您的程序集(不使用 DacPac)。
如果确认,您可以暂时禁用严格安全 - 使用 sp_configure 更改选项 clr strict security。
作为最终解决方案,您应该开始签署您的程序集。

https://docs.microsoft.com/en-us/sql/t-sql/statements/create-assembly-transact-sql?view=sql-server-ver15

CLR 使用 .NET Framework 中的代码访问安全性 (CAS),不再支持将其作为安全边界。使用 PERMISSION_SET = SAFE 创建的 CLR 程序集可能能够访问外部系统资源、调用非托管代码并获得系统管理员权限。从 SQL Server 2017 (14.x) 开始,引入了一个名为 clr strict security 的 sp_configure 选项,以增强 CLR 程序集的安全性。默认情况下启用 clr strict security,并将 SAFE 和 EXTERNAL_ACCESS 程序集视为标记为 UNSAFE。为了向后兼容,可以禁用 clr strict 安全选项,但不建议这样做。Microsoft 建议使用证书或非对称密钥对所有程序集进行签名,并使用已在 master 数据库中授予 UNSAFE ASSEMBLY 权限的相应登录名。

于 2020-03-10T21:39:30.153 回答