我有一个静态类,它动态加载.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服务帐户“完全访问”提供给磁盘上的动态组件文件。我使用语法复制了我的dyamic程序集:
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.
答案 0 :(得分:2)
正如错误消息所述,SQL Server完全禁止动态程序集加载 - 即使在不安全的情况下也是如此。 Assembly.Load调用成功的唯一方法是,程序集已经通过CREATE ASSEMBLY或GAC和list of supported ("blessed") assemblies加载到数据库中。 sqlclr blog上还有另一篇文章。
答案 1 :(得分:1)
我知道这是一个非常古老的问题,但我最近找到了实现你想要的方法。当您尝试在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注册了程序集。
答案 2 :(得分:0)
我猜你在创建组件时已经将PERMISSION_SET设置为SAFE(如果你没有指定它,这将是默认设置)。如果你想这样做,你需要将它改为EXTERNAL_ACCESS或UNSAFE。
答案 3 :(得分:0)
我是一名致力于SQL-CLR集成的开发人员@微软,所以我可以提供帮助。
要实现您的目标,您需要做两件事:
请注意,做所有这些事情有几个负面的副作用:
如果可能,请考虑重新设计您的应用,以便将所有需要的程序集预先加载到数据库本身。
[编辑:如果上述任何一项都无法在MSDN论坛上提出最佳建议]。