【发布时间】:2019-07-24 00:50:51
【问题描述】:
我已将我的本地 SQL Server 2008 R2 数据库迁移到 Azure SQL Server 托管实例 (SQL Server 2017)。一个数据库是存档(只读)数据库,一个是 OLTP 数据库,第三个是实用程序数据库,我在其中保存通用函数、存储过程和维护脚本。除了实用程序数据库中的 CLR 程序集外,所有三个数据库的一切都进行得非常顺利。该程序集在 TSQL 代码中提供正则表达式功能 - 非常有用!我基于 Phil Factor 代码here。最初,它是从已编译的 DLL 加载到本地数据库中的。它在那里像冠军一样工作。但在 SQL MI 上,运行使用 CLR 函数之一的 SP 时出现以下错误。
消息 10314,级别 16,状态 11,过程 dbo.globalSearch,第 22 行 [批处理开始第 2 行]
尝试加载程序集 id 65541 时,Microsoft .NET Framework 发生错误。服务器可能资源不足,或者程序集可能不受信任。再次运行查询,或查看文档以了解如何解决程序集信任问题。有关此错误的详细信息:
System.IO.FileLoadException:无法加载文件或程序集“regexsqlclr,Version=0.0.0.0,Culture=neutral,PublicKeyToken=null”或其依赖项之一。发生与安全有关的错误。 (HRESULT 异常:0x8013150A)
System.IO.FileLoadException:
在 System.Reflection.RuntimeAssembly._nLoad(AssemblyName 文件名、字符串代码库、证据 assemblySecurity、RuntimeAssembly locationHint、StackCrawlMark 和 stackMark、IntPtr pPrivHostBinder、布尔 throwOnFileNotFound、布尔 forIntrospection、布尔suppressSecurityChecks)
在 System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef,证据 assemblySecurity,RuntimeAssembly reqAssembly,StackCrawlMark 和 stackMark,IntPtr pPrivHostBinder,布尔 throwOnFileNotFound,布尔 forIntrospection,布尔suppressSecurityChecks)
在 System.Reflection.RuntimeAssembly.InternalLoad(字符串 assemblyString,证据 assemblySecurity,StackCrawlMark 和 stackMark,IntPtr pPrivHostBinder,Boolean forIntrospection)
在 System.Reflection.RuntimeAssembly.InternalLoad(字符串 assemblyString,证据 assemblySecurity,StackCrawlMark 和 stackMark,Boolean for Introspection)
在 System.Reflection.Assembly.Load(String assemblyString)
我已经尝试使用this MSDN 帖子中的步骤解决程序集信任问题,具体执行
sys.sp_add_trusted_assembly
成功了,但什么也没改变。然后我想,既然它暗示它不能从文件中加载,这 似乎 是有道理的,因为该文件在我无法访问文件系统的 SQL MI 中不存在,我应该尝试从varbinary 删除和重新创建。我只是说它似乎是有道理的,因为除了我最初从中加载它的服务器之外,该文件也不存在于我的任何其他本地服务器上,并且它在所有服务器上都能完美运行.但是,我愿意尝试任何事情!因此,我使用 SSMS 将程序集编写为 DROP 和 CREATE,它使用 FROM BINARY 语法,并同样编写了所有函数的脚本。 CREATE ASSEMBLY 成功了,所以我认为我在正确的轨道上。然后我尝试创建第一个函数和BAM,另一个错误!这次错误读取
消息 6505,级别 16,状态 2,过程 RegexIndex,第 2 行
在程序集“RegexFunctions”中找不到类型“RegexSQLCLR.RegularExpressionFunctions”。
我已经在谷歌上搜索了几个小时,试图找到解决该问题的方法,但运气却为零。尽管 EXTERNAL NAME 子句的类部分的语法对于从文件加载的程序集非常有效。我验证了由 SSMS 编写的 varbinary 与原始 DLL 的二进制文件相同。 Microsoft 论坛上的某个人建议我确保使用 Any CPU 选项编译 DLL - 确实如此。作为健全性检查,我在其中一台本地服务器(即DROP 和CREATE ASSEMBLY FROM BINARY)上执行了相同的过程,得到了完全相同的结果:我无法加载任何 CLR 函数!我已经尝试了我能想到的所有可能的类名排列,但无济于事。这是CREATE ASSEMBLY 和CREATE FUNCTION 的代码
CREATE ASSEMBLY [RegexFunction]
AUTHORIZATION [dbo]
FROM 0x4D5A90000 *truncated_for_brevity*
WITH PERMISSION_SET = SAFE
CREATE FUNCTION RegExIndex
(
@Pattern NVARCHAR(4000),
@Input NVARCHAR(MAX),
@Options int
)
RETURNS int
AS EXTERNAL NAME
RegexFunction.[RegexSQLCLR.RegularExpressionFunctions].RegExIndex
GO
RegexSQLCLR 是原始 DLL 的名称,RegularExpressionFunctions 是类的名称。 RegexSQLCLR也是使用CREATE ASSEMBLY FROM BINARY后在sys.assembly_files的name列中指定的名称;否则,原始 DLL 的完整路径位于 name 列中。
【问题讨论】:
-
当我们试图解决这个问题时,您为什么不尝试安装我创建的 SQLCLR 库SQL#,因为它包含相当多的 RegEx 函数和许多其他内容。您不需要所有程序集,因此您可以在标题注释下方的部分中将一些设置为“0”(例如
Network、OS、Twitterizer)和@MaxAllowedAccessLevel = 1。跨度> -
@SolomonRutzky 谢谢,我会看看它。顺便说一句,我确实找到了答案(见下文)。这两天我再也回不来了!至少这使得最初的 CLR 工作。但我仍然很好奇为什么
CREATE ASSEMBLY FROM BINARY会破坏托管实例和 SQL Server 2008 R2 上的EXTERNAL NAME子句的语法。如果有人对此有答案,我很想听听!在我进行的所有搜索中,我还没有找到任何人发布了一个实际有效的CREATE ASSEMBLY FROM BINARY示例。 -
罗恩,不,
TRUSTWORTHY ON是不是答案...._ever_....您是否将这些数据库恢复到托管实例?你为什么要重新加载 SQLCLR 的东西?...如果是因为安全错误,那很容易在不重新加载的情况下修复..但仍然需要准确了解您在做什么。 -
我使用 Azure SQL 迁移服务将 DB 加载到 MI。因此,这本身并不是真正的传统修复。我正在重新加载 SQLCLR,因为我的想法已经用完了。如果您知道在没有
TRUSTWORTHY ON的情况下解决安全问题的另一种方法,我很乐意听到。 -
我现在正在发布一个答案......但它并不短:(主要是因为修复这个问题的各种尝试导致了这里的多个问题......
标签: .net sql-server .net-assembly sqlclr azure-sql-managed-instance