使用 ICSharpCode.SharpZipLib 的项目的 SQLCLR 发布失败

SQLCLR-Publish fail for project using ICSharpCode.SharpZipLib

我有一个 sql clr,它有一些函数和存储过程。我有一个 EXTERNAL_ACCESS 模式的项目和一个签名密钥。 - 工作正常。

我在使用 ICSharpcode.SharpZipLib 的项目中添加了另一个函数。我最初遇到版本不兼容错误,我想我按照另一个 post.

上的说明解决了这个问题

项目构建正常,但现在我在项目的最后阶段(SQL 服务器数据库项目)出现以下错误。这是在我的本地机器上,我有管理员权限。

Creating [ICSharpCode.SharpZipLib]... (47,1): SQL72014: .Net SqlClient Data Provider: Msg 6211, Level 16, State 1, Line 1 CREATE ASSEMBLY failed because type '<PrivateImplementationDetails>' in safe assembly 'ICSharpCode.SharpZipLib' has a static field '$$method0x6000014-1'. Attributes of static fields in safe assemblies must be marked readonly in Visual C#, ReadOnly in Visual Basic, or initonly in Visual C++ and intermediate language. (47,0): SQL72045: Script execution error. The executed script: CREATE ASSEMBLY [ICSharpCode.SharpZipLib] AUTHORIZATION [dbo] FROM 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0103003877BE5A0000000000000000E00002210B010B000000020000200000000000009E1B02000020000000200200000040000020000000100000040000000000000004000000000000000060020000100000000000000300408500001000001000000000100000100000000000001000000000000000000000004C1B02004F000000002002003804000000000000000000000000000000000000004002000C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E74657874000000A4FB0100002000000000020000100000000000000000000000000000200000602E7273726300000038040000002002000010000000100200000000000000000000000000400000402E72656C6F6300000C000000004002000 An error occurred while the batch was being executed.

感谢任何帮助! 谢谢, 萨蒂亚

我想第一件事是看看你是否可以不用 IcSharpcode.SharpZipLib。如果不是那么:

如果您有权访问 IcSharpcode.SharpZipLib 的源代码,您可以将静态更改为 read-only。

最后一个选项是使用 PERMISSION_SET = UNSAFE 部署程序集。

与 OS 上的 CLR 主机 运行 相比,在 SQL 服务器中运行的 CLR 主机受到高度限制。限制的原因之一是应用程序域在会话之间共享。因此,每个执行特定 SQLCLR 方法(无论是存储过程、函数、User-Defined 类型、User-Defined 聚合还是触发器)的每个人都在同一个静态 [=30] 中执行相同的方法=] 在同一个应用程序域中。因此,静态 class 变量是共享资源,除非您在使用它们时非常小心谨慎,否则它们很容易导致竞争条件和奇怪的(和 difficult-to-debug)行为。

错误消息是关于这个的,但它也有点误导,因为它提到 SAFE 程序集不允许这样的事情。更准确地说,是非 UNSAFE 程序集不允许这样的事情(即 SAFEEXTERNAL_ACCESS 都不允许)。

因此,正如 Niels 在他的回答中提到的,您 可以 将程序集标记为 UNSAFE,它将会加载并且可能会工作。但是,除非您知道该变量(以及任何其他标记为静态但尚未提及的变量)是如何使用的,否则如果一个会话覆盖了另一个会话仍在使用的值,它可能会导致竞争条件。或者有可能保留以前的值,这可能会对下一个调用者产生不利影响。在尝试将程序集设置为 UNSAFE.

之前,您需要通读代码以确保这不是问题

虽然不是那么快速和容易,但您确实需要从更新代码开始,将这些静态变量标记为只读,并尝试重新编译以确保在整个代码中没有尝试写入该变量。如果代码的其他部分确实写入了该静态变量,那么您需要重构代码或找到其他代码来做同样的事情。我 运行 几年前进入这个项目并选择使用 DotNetZip for my SQL# 项目,尽管我仍然需要对静态变量等内容进行小的修改。