【问题标题】:redeploying a .NET assembly that contains CLR stored procedures重新部署包含 CLR 存储过程的 .NET 程序集
【发布时间】:2019-04-29 00:22:43
【问题描述】:

我已经编写了一个 CLR 存储过程,它位于程序集中。

我有一个构建系统,可以从我们的源代码控制存储库自动构建和部署 .net 应用程序。

我希望这两个东西一起工作,这样我就可以重新部署承载 CLR 存储过程的程序集。

但是看起来,与 IIS 不同,简单地替换二进制文件是行不通的。似乎您必须在数据库上删除组件。为了做到这一点,您需要删除所有引用该程序集的对象。

这在一个方面似乎是合理的 - 即从数据库完整性的角度来看 - 而在另一个方面是不合理的 - 适用于运行时评估一般 .NET 依赖项的 JIT 方法。

那么,是否有可能做一些事情,这样我就可以替换二进制文件,然后给 SQL Server 一个刺激,让它确定新程序集满足所有要求(即,具有正确的公共命名空间、类型、方法等)满足绑定到它的存储过程)。

【问题讨论】:

    标签: sql-server stored-procedures deployment continuous-integration sqlclr


    【解决方案1】:

    CLR 程序集存储在数据库中,而不是磁盘上,因此您不能简单地替换一些二进制 dll。要刷新它们,请使用 ALTER ASSEMBLY [assemblyname] FROM 'disklocation'

    【讨论】:

      【解决方案2】:

      简短的回答是“不,它不会以这种方式工作”。正如 Remus 所指出的,SQL Server 将程序集存储在您的数据库中,而不是文件系统中的某个位置。因此,没有这样的地方被服务器监控,也没有你应该放置更新的二进制文件的地方。

      将更新的程序集上传到数据库应该是部署过程中不可或缺的一部分。并且这样做的唯一方法是明确执行以下操作:

      1. 删除在程序集中定义的所有对象(即所有外部 SP/UDF/触发器/类型)
      2. 删除程序集
      3. 创建程序集 - 使用“FROM 'disklocation'”(根据 Remus 的建议,但请注意路径应引用 SQL Server 的本地路径)或“FROM 'binary content'”
      4. 创建所有 [外部] 对象

      步骤 1 实际上可以在 T-SQL 中以通用方式实现(因此您不必显式列出对象)。但是除了自定义工具(它将使用反射来发现程序集内容并生成适当的 T-SQL 以创建所有对象)之外,p.4 没有这种方法。

      【讨论】:

      • “第 1 步实际上可以以通用方式在 T-SQL 中实现”——如何以最简单的方式做到这一点?
      • “但是除了自定义工具,p.4 没有这样的方法”——你碰巧知道任何这样的工具的名称吗?
      • @tbone Here's a T-SQL script for a stored procedure 执行 [1] 和 [2]。对于 [4],我使用数据库构建/比较/模式同步工具 DB Ghost,因此我为版本控制项目/存储库中的每个“外部”对象都有一个 T-SQL 拖放和创建脚本对于我的数据库。数据库工具有效地运行所有这些脚本,所以我没有使用使用反射来自动发现程序集中的 CLR 对象的工具。
      • 这是对完整更新过程的一个很好的描述,但我认为 OP 实际上会询问我们是否只能在所有函数/proc 签名未更改的情况下更新程序集......这确实发生在改变组装。
      【解决方案3】:

      正如Remus's answer 所述,您可以使用ALTER ASSEMBLY ... 更新程序集。

      来自 MSDN 页面 ALTER ASSEMBLY (Transact-SQL) for SQL Server 2008 R2 [强调我的]:

      如果指定了 FROM 子句,ALTER ASSEMBLY 会根据所提供模块的最新副本更新程序集。由于 SQL Server 实例中可能存在已针对程序集定义的 CLR 函数、存储过程、触发器、数据类型和用户定义的聚合函数,因此 ALTER ASSEMBLY 语句将它们重新绑定到程序集的最新实现。 要完成这种重新绑定,映射到 CLR 函数、存储过程和触发器的方法必须仍然存在于具有相同签名的修改后的程序集中。 实现 CLR 用户定义类型和用户定义的类聚合函数仍必须满足作为用户定义类型或聚合的要求。

      因此,如果引用程序集的函数、存储过程等没有更改,您可以简单地更新程序集。此外,这样做不会中断当前正在运行的会话;来自与上述相同的 MSDN 页面:

      ALTER ASSEMBLY 不会中断正在修改的程序集中运行代码的当前正在运行的会话。当前会话通过使用程序集的未更改位来完成执行。

      但是,您可以很容易地自动重新部署程序集及其依赖对象,但通常要这样做,您需要删除并重新创建它。如果这样做,您可能会发现通过将程序集“嵌入”到脚本中更容易部署程序集,方法是首先将程序集文件的字节转换为十六进制数字,然后将其包含在相关的CREATE ASSEMBLY 语句中。

      【讨论】:

        【解决方案4】:

        我同意 AlexS 的建议,除了最后一句话。

        首先,反射不会真正起作用,因为 CLR 函数中使用的数据类型不一定确定 SQL 数据类型。例如,您可以在 CLR 端使用 SqlString,但在 SQL 端使用 NVARCHAR(50) 或 NVARCHAR(MAX) 而不是 NVARCHAR(4000)。

        但是,仍然可以自动执行此操作。您应该使用源代码存储库来存储指向 CLR 代码的存储过程和函数定义,就像存储任何存储过程或函数一样。因此,您可以获取所有这些定义并作为第 4 步运行所有 CREATE PROCEDURE 和 CREATE FUNCTION 语句。

        此外,步骤 1 和 2 可以是单个 SQL 脚本。

        基本上,整个过程可以自动化:)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-24
          • 1970-01-01
          相关资源
          最近更新 更多