SQLCLR:如何将程序集 Npgsql.dll 添加到数据库?
Posted
技术标签:
【中文标题】SQLCLR:如何将程序集 Npgsql.dll 添加到数据库?【英文标题】:SQLCLR: How to add assembly Npgsql.dll to database? 【发布时间】:2015-11-09 04:11:10 【问题描述】:我想从 SQCLR 过程执行 PostgreSQL 命令。 当我添加 Mono.Security.dll 我收到错误:
Msg 6218, Level 16, State 2, Line 33
CREATE ASSEMBLY for assembly 'Mono.Security' failed because assembly 'Mono.Security' 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
[ : Mono.Math.BigInteger+Kernel::Multiply][mdToken=0x600005d][offset 0x0000001C][found address of Int32][expected unmanaged pointer] Unexpected type on the stack.
[ : Mono.Math.BigInteger+Kernel::Multiply][mdToken=0x600005d][offset 0x00000039][found address of Int32][expected unmanaged pointer] Unexpected type on the stack.
[ : Mono.Math.BigInteger+Kernel::Multiply][mdToken=0x600005d][offset 0x00000059][found address of Int32][expected unmanaged pointer] Unexpected type on the stack.
是否可以在 SQLCLR 过程中使用 Npgsql?
【问题讨论】:
【参考方案1】:首先,我将按照所述回答问题。但其次,将链接服务器添加到 PostgreSQL 很可能远更好,我在处理 SQLCLR 错误后解决了这个问题。
SQLCLR 信息
如果这要通过 SQLCLR 工作,最快/最简单的方法是:
ALTER
数据库为TRUSTWORTHY ON
在您的 CREATE ASSEMBLY
查询中包含 WITH PERMISSION_SET = UNSAFE
如果任何引用的程序集位于同一文件夹中,它们将自动上传。所以也许尝试从加载 Npgsql.dll 开始?
现在,这项工作要求您加载到 SQL Server 中的所有程序集都是“纯”MSIL 程序集。如果有任何“混合”(包含 MSIL 和本机 C++),那么它们将无法加载,您将不得不寻找其他解决方案,例如编写可以通过 xp_cmdshell
或其他方式调用的控制台应用程序。
如果上述方法确实有效,那么不需要将数据库设置为 TRUSTWORTHY ON
的更好方法是从这些程序集中的私钥创建一个非对称密钥(假设它们是强命名的)。
非 SQLCLR 信息
所有这些:如果可能的话,创建一个到 PostgreSQL 的链接服务器,然后在通过 SQLCLR 提交的查询中在常规 T-SQL 和中进行链接服务器调用(因为 SQLCLR 不执行 SQL,它只是像任何其他客户端软件一样将其传递给 SQL Server)。这将避免使用UNSAFE
程序集可能遇到的一些潜在问题。这里有两个资源来处理这个设置:
SQL Server and PostgreSQL Linked Server Configuration - Part 2
SQL Server 2012: Add a linked server to PostgreSQL
更新:
如果使用的 SQL Server 版本是 2012 或更高版本,则在执行 CREATE ASSEMBLY
时调用的验证过程中的行为实际上可能会略有变化。查看确切的错误消息,我们可以看到问题的根源在Mono.Math.BigInteger+Kernel::Multiply
。由于 Mono 项目是开源的,我们应该可以看一下源代码。我在 GitHub 上找到了源文件 Mono.Security/Mono.Math/BigInteger.cs,在第 2097 行找到了 Kernel
类的 Multiply
方法,其签名为:
public static unsafe void Multiply (uint [] x, uint xOffset, uint xLen, uint [] y,
uint yOffset, uint yLen, uint [] d, uint dOffset)
SQL Server 是否应该抱怨这是以下线程的主题,该线程讨论了与 Oracle 驱动程序相关的一个非常相似的问题(也出现“堆栈上的意外类型”错误):
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/4e6a5407-7daa-417d-a7ab-2522dc4ee927/sqlclr-create-assembly-validation-in-sql-2012-vs-2008?forum=sqlnetfx
建议将System.Data.OleDB 与适当的OLEDB 提供程序一起使用。我从 PostgreSQL 官方网站的Software Catalogue - Drivers and interfaces 页面中找到了以下两个选项:
PGNP:似乎没有免费版,但他们有试用版。 PgOleDb:免费,但似乎自 2006 年 4 月 17 日以来没有更新。另一个选项可能是通过System.Data.Odbc 和 ODBC 提供程序使用 ODBC。我从同一个 PostgreSQL.com 页面中找到了以下两个选项:
psqlODBC:官方 PostgreSQL ODBC 驱动程序。截至 2015 年 8 月 16 日,此驱动程序的最新更新是 2014 年 10 月 26 日。
ODBC Driver for PostgreSQL:似乎没有免费版,但他们有 30 天试用版。
OLEDB 和 ODBC 选项都应该在 SQLCLR 和链接服务器中工作。
【讨论】:
1.加载第一个 npgsql 给出相同的结果:消息 6218,级别 16,状态 2,第 36 行为程序集“Npgsql”创建程序集失败,因为程序集“Mono.Security”验证失败。检查引用的程序集是否是最新的并且受信任(对于 external_access 或不安全)以在数据库中执行。如果有任何 CLR 验证器错误消息将跟随此消息 [ : Mono.Math.BigInteger+Kernel::Multiply][mdToken=0x600005d][offset 0x0000001C][found address of Int32][expected unmanaged pointer] ... 可能 Mono.Security.dll 是混合程序集。关于链接服务器,您是对的,但很有趣:是否可以使用 SQCLR 中的 Npgsql @Oleg 我应该早点问:你使用的是什么版本的东西? SQL 服务器? Npgsql 驱动程序?您是否在服务器上安装了最新版本的 .NET?我添加了一个包含更多信息的 UPDATE 部分,还有一些我正在检查的其他线索,稍后将添加到 UPDATE 部分。 SQL Server 版本 >=SQL2008,这就是为什么我必须使用程序集 @Oleg 昨天我下载了 Npgsql v2.2.5 并尝试将 Mono.Security.dll 导入 SQL Server 2014。我遇到了同样的错误。我还在上面运行了 PEVERIFY 并收到了完全相同的错误消息。今天我将尝试在 SQL Server 2005 或 2008 R2 上进行测试,看看是否会出现相同的错误。我认为目前这不是 .NET 版本问题。所以 ODBC 路由看起来仍然很有希望,因为它应该可以在 SQLCLR 和链接服务器/OPENROWSET
中使用。你用的是什么版本的 Npgsql?以上是关于SQLCLR:如何将程序集 Npgsql.dll 添加到数据库?的主要内容,如果未能解决你的问题,请参考以下文章
引用 SQL 数据库项目 (SQLCLR) 引发“找不到类型或命名空间”错误
如何在使用 SQLCLR 用户定义的聚合函数 (UDA) 时提高查询性能