.net - CREATE ASSEMBLY 失败,返回 "Unable to resolve token"

标签 .net sql-server .net-assembly sqlclr sql-server-2016

我正在尝试将一些 CLR 代码上传到 SQL Server 2016(开发人员版)实例。总体来说,结构是这样的:

  • 一个 CLR UDF 依赖于程序集 A
  • 另一个 CLR UDF 依赖于程序集 B
  • AB 都依赖于程序集C

.sqlproj 的目标框架是 4.0。程序集 AB 是针对 .net4.0 构建的。程序集 C 是针对 .net2.0 构建的。所有程序集都设置为 Model Aware: TruePermission Set: Safe。所有程序集均未签名。

当我将 .sqlproj 发布到数据库服务器时,程序集 CB 运行良好,但程序集 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

我花了大约一天的时间研究这个主题,但没有找到任何有用的东西。因此,我们将不胜感激任何想法。

更新 1:设置所有程序集的 Permission Set 属性并将数据库 trustworthy 属性设置为 ON 有效,现在已成功部署程序集。但是,现在我无法调用 UDF,因为它们不受信任 :) 我敢肯定,这是可以解决的,但这不是问题的真正解决方案。而且我仍然不明白为什么它不适用于 Permission Set: Safe

关于服务器和开发机器上的 .NET 版本。开发机器是 Win 10。SQL Server 在 WinServer 2012 R2 Standard Core 上的虚拟机中运行。两者都安装了所有最新更新。服务器上安装的 .NET 版本是(使用此片段 https://stackoverflow.com/a/3495491/664178 ):

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 Server 2014 引擎)时也观察到了完全相同的行为,因此问题可能与 SQL Server 2016 无关.

在 Windows Server 上安装 .NET 3.5(Install-WindowsFeature NET-Framework-Core)也没有影响这种情况。

最佳答案

我的测试表明这里的问题是如何指定对 BigInteger 类库的引用。查看 PaillierExt.csproj 文件,它显示引用包括版本信息:

<Reference Include="BigInteger, Version=1.0.4.36383, Culture=neutral, processorArchitecture=MSIL">

但是,ElGamalExt.csproj 文件将引用(对于同一 DLL)显示为只是 DLL 的名称:

<Reference Include="BigInteger">

似乎在数据库项目中引用的默认行为是引用,如果给定版本号,则隐含 Version Specific = false,而在类库中,如果给出引用版本号,Version Specific 隐含为 true。在这种情况下,显式设置对 Specific Version = false 的引用可能会有所帮助。

通过将源代码(不起作用的原始代码,而不是移动内容的更新代码)复制到 3 个新创建的类库项目中,我能够成功构建和加载所有这 3 个项目。我将项目 GUID 和引用之类的内容复制到新的 .csproj 文件中,但没有复制该特定引用的特定版本信息。然后我能够创建一个数据库项目和一个引用 PaillierExtElGamalExt 方法的 SQLCLR 对象。一切都按预期进行。

我相信这也解释了为什么它在程序集注册为 PERMISSION_SET = UNSAFE 时起作用:很可能是特定版本信息和隐含的 Specific Version = true 属性是对 CLR 的建议,当程序集是 SAFEEXTERNAL_ACCESS 时遵循,但将它们设置为 UNSAFE 允许绕过表示偏好。

附言我不确定这是否重要,但与我通常所做的另一个不同之处是,在 AssemblyInfo.cs 文件中,AssemblyVersion 属性使用的是 * 用于构建 #。我没有发现这是一个复杂的因素,但如果有人在从引用中删除特定于版本的信息后仍然遇到问题,请尝试用静态值替换 *。原因是如果版本 # 需要是“特定的”,那么在每次构建时更改版本 # 的一部分可能无济于事 ;-)。

有关测试等的详细信息可以在 discussion 中找到.

关于.net - CREATE ASSEMBLY 失败,返回 "Unable to resolve token",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38035247/

相关文章:

c# - 为什么接受引用类型的泛型方法不接受可空类型作为参数?

c# - SQLCriterion ArgumentOutOfRangeException

c# - 使用 ASP.NET MVC3 处理注册向导的正确方法是什么?

c# - 是否有标准算法将重叠对象平衡到桶中?

.net-assembly - 在PCL中获取程序集版本

sql-server - 将 varchar 转换为十进制在 SQL Server 上不起作用

sql-server - 使用 SSDT 2016 部署报告会生成错误

SQL Server FOR XML Path 使重复节点

.net - 是否可以在 SQL Server 2014 中为 .NET 框架程序集创建非对称 key ?

c# - GetExecutingAssembly() 用于不同程序集中的派生类