2

我有一个静态类,它动态加载 .NET 程序集(使用Assembly.LoadFile方法)我收到以下错误消息:

Msg 6522, Level 16, State 2, Line 3
A .NET Framework error occurred during execution of user-defined routine or aggregate "MySQLCLRUDFFunction": 
System.TypeInitializationException: The type initializer for 'MyClassName' threw an exception. ---> System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed

.

当我尝试使用此声明分配 CAS 安全性时

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]

相反,我得到了这个异常

Msg 6522, Level 16, State 2, Line 2
A .NET Framework error occurred during execution of user-defined routine or aggregate "MySQLCLRUDFFunction": 
System.TypeInitializationException: The type initializer for 'MyClassName' threw an exception. ---> System.Security.SecurityException: Request failed.

注意:我已经为我的 SQL Server 服务帐户提供了对磁盘上动态程序集文件的“完全访问权限”。我使用语法复制了我的动态程序集:

create Assembly TestAssembly
    From 'C:\MyTestAssembly.dll';
--Alter Assembly to copy dynamic assembly file
Alter Assembly TestAssembly add file from 'C:\mydynamicassembly.dll';

转动TRUSTWORTHY ON和设置后,PERMISSION_SET = UNSAFE我现在得到了这个异常

Msg 6522, Level 16, State 2, Line 2
A .NET Framework error occurred during execution of user-defined routine or aggregate "MySQLCLRUDFFunction": 
System.TypeInitializationException: The type initializer for 'MyClassName' threw an exception. ---> System.IO.FileLoadException: LoadFrom(), LoadFile(), Load(byte[]) and LoadModule() have been disabled by the host.
4

4 回答 4

2

正如错误消息所述,SQL Server 完全不允许动态程序集加载 - 即使在不安全的情况下也是如此。Assembly.Load 调用成功的唯一方法是程序集是否已通过 CREATE ASSEMBLY 或 GAC 加载到数据库中以及受支持(“祝福”)程序集的列表中在sqlclr 博客上有另一篇文章。

于 2010-02-24T03:30:39.367 回答
1

我知道这是一个非常古老的问题,但我最近找到了一种方法来实现你想要的。当您尝试Assembly.Load(...)在 SQL CLR 托管程序集中使用时,它会显式失败,这是设计使然,即使使用PERMISSION_SET = UNSAFE. 这是为了保证数据库服务器的稳定性。

加载动态程序集的技术是先注册它们,然后使用Type.GetType(...)传递完全限定的类型名称(包括程序集版本信息)来解析类型。

以下是步骤:

1.编译类型,并在磁盘上完成(即不创建内存程序集)。该CompilerResults类型将具有CompiledAssembly属性和PathToCompiledAssembly属性。使用后者,因为访问该CompiledAssembly属性将尝试使用Assembly.Load.

2.使用路径,我从我的代码(使用new SqlConnection("Context Connection = true"))调用存储过程,我传入程序集的名称(我已经预先确定)和编译的程序集路径:

CREATE PROCEDURE re.CreateAssembly
    @name VARCHAR(100),
    @path VARCHAR(1000)
AS
BEGIN
    DECLARE @sql NVARCHAR(2000)
    SET @sql = N'CREATE ASSEMBLY [' + @name + '] AUTHORIZATION [DatabaseUser] FROM ''' + @path + ''' WITH PERMISSION_SET + SAFE';
    EXEC sp_executesql @sql;
END
GO

3.使用您的预定名称,您可以使用Type.GetType(...),例如:

string typeName = "MyCompiledAssembly.MyClass, MyCompiledAssembly, Version=0.0.0.0, Culture=Neutral, PublicKeyToken=null, ProcessorArchitecture=MSIL";
Type type = Type.GetType(typeName);

当 SQLCLR 尝试解析类型时,它应该会找到它,因为在第 2 步中,您已经向 Sql Server 注册了程序集。

于 2011-09-21T07:13:45.103 回答
0

我猜您在 CREATE ASSEMBLY 时已将 PERMISSION_SET 设置为 SAFE(如果您未指定,这将是默认设置)。如果您想这样做,您需要将其更改为 EXTERNAL_ACCESS 或 UNSAFE。

http://msdn.microsoft.com/en-us/library/ms189524.aspx

于 2009-11-12T16:28:25.990 回答
0

我是从事 SQL-CLR 集成的开发人员@Microsoft 之一,所以我可以提供帮助。

为了实现你想要的,你需要做两件事:

  1. 将数据库标记为 TRUSTWORTHY
  2. 将程序集标记为不安全(数据库必须是可信赖的)
  3. 运行 SQL Server 的帐户必须有权访问文件系统上的文件。通常文件位于网络共享上,但 SQL Server 是在没有访问网络权限的本地帐户下运行的,因此这通常是一个问题。默认安装中的 SQL Express 没有 C: 权限。

请注意,做所有这些事情有几个负面影响:

  1. 严重的安全隐患 - 您实际上将实例的控制权交给了不安全汇编中的代码,因为它现在可以使用原始指针来访问/更改引擎中的任何内容。
  2. 稳定性——出于同样的原因,您也放弃了稳定性保证。
  3. 可移植性和灾难恢复 - 如果您的数据库必须移动到其他地方进行负载平衡或在机器故障后从备份中恢复,您将不会在新机器上拥有 mydynamicassembly.dll。

如果可能,请考虑重新设计您的应用程序,以便将所有需要的程序集预加载到数据库本身中。

[编辑:如果以上都没有帮助,最好在 MSDN 论坛上提问]。

于 2009-11-12T16:41:20.627 回答