4

我写了一个程序集中的 CLR 存储过程。

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

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

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

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

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

4

4 回答 4

6

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

于 2009-08-19T18:15:27.143 回答
3

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

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

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

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

于 2009-08-19T19:36:09.897 回答
2

正如Remus 的回答所述,您可以使用它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语句中,将程序集“嵌入”到脚本中会更容易部署程序集。

于 2014-08-18T15:46:20.897 回答
0

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

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

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

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

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

于 2011-01-22T15:12:34.443 回答