CREATE ASSEMBLY 失败 "Unable to resolve token"
CREATE ASSEMBLY fails with "Unable to resolve token"
我正在尝试将一些 CLR 代码上传到 SQL Server 2016(开发人员版)实例。总体来说,结构是这样的:
- 一个 CLR UDF 依赖于程序集
A
- 另一个 CLR UDF 依赖于程序集
B
A
和 B
都取决于程序集 C
.sqlproj 的目标框架是 4.0。程序集 A
和 B
是针对 .net4.0 构建的。程序集 C
是针对 .net2.0 构建的。所有程序集都设置为 Model Aware: True
、Permission Set: Safe
。所有程序集都未签名。
当我将 .sqlproj 发布到数据库服务器时,程序集 C
和 B
运行良好,但程序集 A
失败并显示:
(276,1): SQL72014: .Net SqlClient Data Provider: Msg 6218, Level 16, State 2,
Line 1 CREATE ASSEMBLY for assembly 'A' failed because assembly 'A' failed
verification. Check if the referenced assemblies are up-to-date and trusted
(for external_access or unsafe) to execute in the database. CLR Verifier error
messages if any will follow this message
[ : A.Class1::Method1][mdToken=0x6000010][offset 0x00000001] Unable to resolve token.
[ : A.Class2::Method2][mdToken=0x6000014][offset 0x0000004C] Unable to resolve token.
[ : A.Class3::Method3][mdToken=0x6000017][offset 0x00000001] Unable to resolve token.
[ : A.Class4::Method4][mdToken=0x6000021][offset 0x0000000C] Unable to resolve token.
(276,0): SQL72045: Script execution error. The executed script:
CREATE ASSEMBLY [A]
AUTHORIZATION [dbo]
FROM 0x4D5A9...002A0
我花了大约一天的时间研究这个主题,但没有找到任何有用的东西。所以任何想法将不胜感激。
UPDATE 1:设置所有程序集的Permission Set
属性并将数据库trustworthy
属性设置为ON
工作,现在已成功部署程序集。但是,现在我无法调用 UDF,因为它们不受信任 :) 我敢肯定,这是可以解决的,但这不是问题的真正解决方案。而且我仍然不明白为什么它不适用于 Permission Set: Safe
.
关于服务器和开发机器上的 .NET 版本。开发机器是 Win 10。 SQL 服务器是 运行 在 WinServer 2012 R2 Standard Core 上的虚拟机中。两者都安装了所有最新更新。服务器上安装的 .NET 版本是(使用此代码段 ):
PSChildName Version Release Product
----------- ------- ------- -------
Client 4.6.01055 394271 4.6.1
Full 4.6.01055 394271 4.6.1
Client 4.0.0.0
在开发机器上:
PSChildName Version Release Product
----------- ------- ------- -------
v2.0.50727 2.0.50727.4927
v3.0 3.0.30729.4926
Windows Communication Foundation 3.0.4506.4926
Windows Presentation Foundation 3.0.6920.4902
v3.5 3.5.30729.4926
Client 4.6.01038 394254 4.6.1
Full 4.6.01038 394254 4.6.1
Client 4.0.0.0
我似乎无法将开发机器上的 .NET 更新到与服务器相同的版本。可能是因为开发机器的 Windows 被设置为延迟更新......这个版本不匹配会不会是问题的根源?
更新 2: 显然,这些 .NET 版本是各自平台的最新版本 (https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx)
更新 3: 我已经尝试了一些进一步的事情。
将数据库项目部署到本地 SQL Server 2016 Express 数据库会产生相同的结果,所以看起来开发和服务器框上的 .NET 版本不匹配是不是问题。
此外,在部署到 LocalDB v12.0(SQL 服务器 2014 引擎时观察到完全相同的行为),所以问题可能不是 SQL 服务器 2016.
在 Windows 服务器 (Install-WindowsFeature NET-Framework-Core
) 上安装 .NET 3.5 也没有影响这种情况。
我的测试表明这里的问题是如何指定对 BigInteger Class 库的引用。查看 PaillierExt.csproj 文件,它显示引用包括版本信息:
<Reference Include="BigInteger, Version=1.0.4.36383, Culture=neutral, processorArchitecture=MSIL">
但是,ElGamalExt.csproj 文件显示引用(对于同一个 DLL)只是 DLL 的名称:
<Reference Include="BigInteger">
似乎数据库项目中引用的默认行为是引用,如果给定版本号,则隐含 Version Specific = false
,而在 Class 库中,如果给出引用版本号 Version Specific
隐含为 true
。在这种情况下,将引用显式设置为 Specific Version = false
.
可能会有所帮助
通过将源代码(无法正常工作的原始代码,而不是移动内容的更新代码)复制到 3 个新创建的 Class 图书馆项目。我将项目 GUID 和引用等内容复制到新的 .csproj 文件中,但没有复制该特定引用的特定版本信息。然后我能够创建一个数据库项目和一个引用 PaillierExt 和 ElGamalExt 方法的 SQLCLR 对象。一切都按预期进行。
我相信这也解释了为什么它在程序集注册为 PERMISSION_SET = UNSAFE
时起作用:很可能是特定版本信息和隐含的 Specific Version = true
属性 是一个建议当程序集是 SAFE
或 EXTERNAL_ACCESS
时遵循的 CLR,但将它们设置为 UNSAFE
允许绕过指定的偏好。
P.S。我不确定这是否重要,但与我通常所做的另一个不同是,在 AssemblyInfo.cs 文件中,AssemblyVersion
属性使用 *
用于生成 #。我没有发现这是一个复杂的因素,但如果有人在从参考中删除版本特定信息后仍然遇到问题,请尝试用静态值替换 *
。原因是如果版本 # 需要是“特定的”,那么在每次构建时更改版本 # 的一部分可能无济于事 ;-).
有关测试等的详细信息可以在 discussion.
中找到
我正在尝试将一些 CLR 代码上传到 SQL Server 2016(开发人员版)实例。总体来说,结构是这样的:
- 一个 CLR UDF 依赖于程序集
A
- 另一个 CLR UDF 依赖于程序集
B
A
和B
都取决于程序集C
.sqlproj 的目标框架是 4.0。程序集 A
和 B
是针对 .net4.0 构建的。程序集 C
是针对 .net2.0 构建的。所有程序集都设置为 Model Aware: True
、Permission Set: Safe
。所有程序集都未签名。
当我将 .sqlproj 发布到数据库服务器时,程序集 C
和 B
运行良好,但程序集 A
失败并显示:
(276,1): SQL72014: .Net SqlClient Data Provider: Msg 6218, Level 16, State 2, Line 1 CREATE ASSEMBLY for assembly 'A' failed because assembly 'A' failed verification. Check if the referenced assemblies are up-to-date and trusted (for external_access or unsafe) to execute in the database. CLR Verifier error messages if any will follow this message [ : A.Class1::Method1][mdToken=0x6000010][offset 0x00000001] Unable to resolve token. [ : A.Class2::Method2][mdToken=0x6000014][offset 0x0000004C] Unable to resolve token. [ : A.Class3::Method3][mdToken=0x6000017][offset 0x00000001] Unable to resolve token. [ : A.Class4::Method4][mdToken=0x6000021][offset 0x0000000C] Unable to resolve token. (276,0): SQL72045: Script execution error. The executed script: CREATE ASSEMBLY [A] AUTHORIZATION [dbo] FROM 0x4D5A9...002A0
我花了大约一天的时间研究这个主题,但没有找到任何有用的东西。所以任何想法将不胜感激。
UPDATE 1:设置所有程序集的Permission Set
属性并将数据库trustworthy
属性设置为ON
工作,现在已成功部署程序集。但是,现在我无法调用 UDF,因为它们不受信任 :) 我敢肯定,这是可以解决的,但这不是问题的真正解决方案。而且我仍然不明白为什么它不适用于 Permission Set: Safe
.
关于服务器和开发机器上的 .NET 版本。开发机器是 Win 10。 SQL 服务器是 运行 在 WinServer 2012 R2 Standard Core 上的虚拟机中。两者都安装了所有最新更新。服务器上安装的 .NET 版本是(使用此代码段 ):
PSChildName Version Release Product ----------- ------- ------- ------- Client 4.6.01055 394271 4.6.1 Full 4.6.01055 394271 4.6.1 Client 4.0.0.0
在开发机器上:
PSChildName Version Release Product ----------- ------- ------- ------- v2.0.50727 2.0.50727.4927 v3.0 3.0.30729.4926 Windows Communication Foundation 3.0.4506.4926 Windows Presentation Foundation 3.0.6920.4902 v3.5 3.5.30729.4926 Client 4.6.01038 394254 4.6.1 Full 4.6.01038 394254 4.6.1 Client 4.0.0.0
我似乎无法将开发机器上的 .NET 更新到与服务器相同的版本。可能是因为开发机器的 Windows 被设置为延迟更新......这个版本不匹配会不会是问题的根源?
更新 2: 显然,这些 .NET 版本是各自平台的最新版本 (https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx)
更新 3: 我已经尝试了一些进一步的事情。
将数据库项目部署到本地 SQL Server 2016 Express 数据库会产生相同的结果,所以看起来开发和服务器框上的 .NET 版本不匹配是不是问题。
此外,在部署到 LocalDB v12.0(SQL 服务器 2014 引擎时观察到完全相同的行为),所以问题可能不是 SQL 服务器 2016.
在 Windows 服务器 (Install-WindowsFeature NET-Framework-Core
) 上安装 .NET 3.5 也没有影响这种情况。
我的测试表明这里的问题是如何指定对 BigInteger Class 库的引用。查看 PaillierExt.csproj 文件,它显示引用包括版本信息:
<Reference Include="BigInteger, Version=1.0.4.36383, Culture=neutral, processorArchitecture=MSIL">
但是,ElGamalExt.csproj 文件显示引用(对于同一个 DLL)只是 DLL 的名称:
<Reference Include="BigInteger">
似乎数据库项目中引用的默认行为是引用,如果给定版本号,则隐含 Version Specific = false
,而在 Class 库中,如果给出引用版本号 Version Specific
隐含为 true
。在这种情况下,将引用显式设置为 Specific Version = false
.
通过将源代码(无法正常工作的原始代码,而不是移动内容的更新代码)复制到 3 个新创建的 Class 图书馆项目。我将项目 GUID 和引用等内容复制到新的 .csproj 文件中,但没有复制该特定引用的特定版本信息。然后我能够创建一个数据库项目和一个引用 PaillierExt 和 ElGamalExt 方法的 SQLCLR 对象。一切都按预期进行。
我相信这也解释了为什么它在程序集注册为 PERMISSION_SET = UNSAFE
时起作用:很可能是特定版本信息和隐含的 Specific Version = true
属性 是一个建议当程序集是 SAFE
或 EXTERNAL_ACCESS
时遵循的 CLR,但将它们设置为 UNSAFE
允许绕过指定的偏好。
P.S。我不确定这是否重要,但与我通常所做的另一个不同是,在 AssemblyInfo.cs 文件中,AssemblyVersion
属性使用 *
用于生成 #。我没有发现这是一个复杂的因素,但如果有人在从参考中删除版本特定信息后仍然遇到问题,请尝试用静态值替换 *
。原因是如果版本 # 需要是“特定的”,那么在每次构建时更改版本 # 的一部分可能无济于事 ;-).
有关测试等的详细信息可以在 discussion.
中找到