重新部署包含 CLR 存储过程的 .NET 程序集

发布于 2024-08-02 17:33:18 字数 403 浏览 9 评论 0原文

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

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

我希望这两件事能够协同工作,以便我可以重新部署托管 CLR 存储过程的程序集。

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

从某种意义上说,这似乎是合理的(即从数据库完整性的角度来看),而从另一种意义上来说,这似乎是不合理的——通常适用于 .NET 依赖关系的运行时评估的 JIT 方法。

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

I have written a CLR stored procedure that is in an assembly.

I have a build system that can auto-build and deploy .net application from our source control repository.

I want the two things to work together so I can redeploy the assembly that hosts the CLR stored proc.

However it looks like, unlike IIS, simply replacing the binaries doesn't work. It seems like you have to DROP ASSEMBLY on the database. In order to do that you need to drop all the objects that reference that assembly.

That seems reasonable in one way -- i.e., from a database integrity point of view-- and unreasonable in another -- the JIT approach that applies for runtime evaluation of dependencies for .NET in general.

So, is it possible to do something so I can replace the binary then give SQL server a kick and make it figure out that the new assembly satisfies all the requirements (i.e., has the right public namespaces, types, methods etc to satisfy the sprocs that are bound to it).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

赢得她心 2024-08-09 17:33:18

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

The CLR assemblies are stored in the database, not on disk, so you cannot simply replace some binary dll. To refresh them you use ALTER ASSEMBLY [assemblyname] FROM 'disklocation'.

有深☉意 2024-08-09 17:33:18

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

将更新的程序集上传到数据库应该是部署过程中不可或缺的一部分。执行此操作的唯一方法是显式执行以下操作:

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

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

Short answer is 'No, it will not work this way'. As it was pointed by Remus, SQL Server stores assemblies inside your database and not somewhere in a file system. Thus there's no such place that is monitored by the server and where you should place updated binaries.

Uploading an updated assembly(ies) to the database should be an integral part of your deployment process. And the only way of doing it to perform the following actions explicitly:

  1. Drop all objects that are defined in an assembly (i.e. all external SPs/UDFs/Triggers/Types)
  2. Drop assembly(ies)
  3. Create assembly(ies) - with either "FROM 'disklocation'" (as advised by Remus, but note that the path should refer to SQL Server's local path) or "FROM 'binary content'"
  4. Create all [external] objects

Step 1 can actually be implemented in T-SQL in a generic way (so you don't have to list objects explicitly). But there's not such way for p.4 except custom tool (which will use reflection in order to discover assembly content and generate appropriate T-SQL for creating all objects).

想你的星星会说话 2024-08-09 17:33:18

正如Remus的回答所述,您可以使用ALTER ASSEMBLY ...来更新程序集。

从 MSDN 页面 ALTER ASSEMBLY (Transact-SQL)对于 SQL Server 2008 R2 [强调我的]:

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

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

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

但是,您可以相当轻松地自动重新部署程序集及其依赖对象,但通常要这样做,您需要删除并重新创建它。如果这样做,您可能会发现通过首先将程序集文件的字节转换为十六进制数字,然后将其包含在相关的CREATE ASSEMBLY 声明。

As Remus's answer states, you can use ALTER ASSEMBLY ... to update an assembly.

From the MSDN page ALTER ASSEMBLY (Transact-SQL) for SQL Server 2008 R2 [emphasis mine]:

If the FROM clause is specified, ALTER ASSEMBLY updates the assembly with respect to the latest copies of the modules provided. Because there might be CLR functions, stored procedures, triggers, data types, and user-defined aggregate functions in the instance of SQL Server that are already defined against the assembly, the ALTER ASSEMBLY statement rebinds them to the latest implementation of the assembly. To accomplish this rebinding, the methods that map to CLR functions, stored procedures, and triggers must still exist in the modified assembly with the same signatures. The classes that implement CLR user-defined types and user-defined aggregate functions must still satisfy the requirements for being a user-defined type or aggregate.

So, if the functions, stored procedures, etc. that reference the assembly haven't changed, you can simply update the assembly. Also, doing so doesn't disrupt currently running sessions; from the same MSDN page as mentioned above:

ALTER ASSEMBLY does not disrupt currently running sessions that are running code in the assembly being modified. Current sessions complete execution by using the unaltered bits of the assembly.

However, you could fairly easily re-deploy an assembly and its dependent objects automatically, but to do so generally, you would need to drop and re-create it. If you do so, you may find it easier to deploy the assembly by 'embedding' it in a script by first converting the bytes of the assembly file to hexadecimal digits which can then be included in the relevant CREATE ASSEMBLY statement.

时光瘦了 2024-08-09 17:33:18

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

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

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

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

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

I agree with what AlexS suggested except the last sentence.

First off, reflection will not truly work as the datatypes used in the CLR functions do not necessarily determine the SQL datatypes. For example, you could have SqlString on the CLR side but use NVARCHAR(50) or NVARCHAR(MAX) instead of NVARCHAR(4000) on the SQL side.

However, it is still possible to automate this. You should be using the source code repository to be storing the Stored Proc and Function definitions that point to the CLR code, just as you would any Stored Proc or Function. So you could grab all of those definitions and run all of the CREATE PROCEDURE and CREATE FUNCTION statements as Step 4.

Also, Steps 1 and 2 can be a single SQL script.

Essentially, this entire process can be automated :).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文