【问题标题】:Sql 2005 CLR Integration - Is Dynamic Assembly Loading supported?Sql 2005 CLR 集成 - 是否支持动态程序集加载?
【发布时间】:2009-11-12 16:14:33
【问题描述】:

我有一个动态加载 .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.

【问题讨论】:

    标签: sql-server-2005 sqlclr


    【解决方案1】:

    正如错误消息所述,SQL Server 完全不允许动态程序集加载 - 即使在不安全的情况下也是如此。 Assembly.Load 调用成功的唯一方法是程序集是否已通过 CREATE ASSEMBLY 或 GAC 以及 list of supported ("blessed") assemblies 加载到数据库中。 sqlclr blog 上还有一篇关于此的帖子。

    【讨论】:

      【解决方案2】:

      我知道这是一个非常古老的问题,但我最近找到了一种方法来实现你想要的。当您尝试在 SQL CLR 托管程序集中使用 Assembly.Load(...) 时,它会显式失败,这是设计使然,即使使用 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 注册了程序集。

      【讨论】:

      • 有趣的方法。只是出于好奇:你什么时候需要使用这样的东西?哪些情况需要动态加载,而事先不知道要加载什么?
      • @srutzky 在撰写本文时,.NET 3.5 仍然存在——我已将我的 OOS 项目 RazorEngine 移植回 .NET 3.5,因此我可以将其安装到 Sql Server 中以在数据库上使用——级错误报告机制。您可以将错误输入 SQL 中的一组表(因为数据库是所有其他系统之间的公分母),它会触发受限制的错误电子邮件。 Razor 用于控制电子邮件模板。由于 RazorEngine 为每个模板生成唯一的 DLL,因此必须加载它们才能执行。
      【解决方案3】:

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

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

      【讨论】:

      • @Greg Beech 和@DenNukem - 感谢您的想法。我尝试进行权限更改,但仍然得到最后一个例外 - 我已经用详细信息编辑了原始问题。并且异常似乎表明程序集的动态加载被禁用...
      • 嗯,这对我来说听起来很确定;如果 SQL Server 已明确禁用它,那么听起来您将无法动态加载程序集。即使在 UNSAFE 模式下,我也不知道这是一个限制。
      【解决方案4】:

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

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

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

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-14
        • 2015-12-16
        • 1970-01-01
        • 2015-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-22
        相关资源
        最近更新 更多