Sql 2005 CLR 集成 - 是否支持动态程序集加载?
我有一个静态类,它动态加载 .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.
I have a static class which loads a .NET assembly dynamically (using Assembly.LoadFile
method)
I get the following error message:
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
.
When I try assign CAS security using this declaration
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
I instead get this exception
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.
Note: I have given my SQL Server service account "Full Access" to my dynamic assemly file on disk. I copied my dyamic assembly using syntax:
create Assembly TestAssembly
From 'C:\MyTestAssembly.dll';
--Alter Assembly to copy dynamic assembly file
Alter Assembly TestAssembly add file from 'C:\mydynamicassembly.dll';
After turning TRUSTWORTHY ON
and setting PERMISSION_SET = UNSAFE
I now get this exception
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
正如错误消息所述,即使在不安全的情况下,SQL Server 也完全不允许动态程序集加载。 Assembly.Load 调用成功的唯一方法是程序集已通过 CREATE ASSEMBLY 加载到数据库中或 GAC 中以及 支持的(“blessed”)程序集列表。 sqlclr 博客上还有另一篇关于此问题的文章。
As the error message states, dynamic assembly loading is completely disallowed by SQL Server - even under unsafe. The only way for Assembly.Load calls to succeed is if the assembly is already loaded in the database via CREATE ASSEMBLY or in the GAC and on the list of supported ("blessed") assemblies. There is another post on this on the sqlclr blog.
我知道这是一个非常老的问题,但我最近找到了一种方法来实现你想要的。当您尝试在 SQL CLR 托管程序集中使用
Assembly.Load(...)
时,它会显式失败,这是设计使然,即使使用PERMISSION_SET = UNSAFE
也是如此。这是为了保证数据库服务器的稳定性。加载动态程序集的技术是首先注册它们,然后使用传入完全限定类型名称(包括程序集版本信息)的
Type.GetType(...)
解析类型。以下是步骤:
1.编译类型,并在磁盘上完成(即不创建内存中程序集)。
CompilerResults
类型将具有CompiledAssembly
属性和PathToCompiledAssembly。
属性。访问CompiledAssembly
属性将尝试使用Assembly.Load
2.使用该路径,我从代码中调用存储过程。 (使用
new SqlConnection("Context Connection = true")
),我传入程序集的名称(我已预先确定)和编译的程序集路径:3.使用您预先确定的名称,您可以使用
Type.GetType(...)
,例如:当 SQLCLR 尝试解析类型时,它应该找到它,因为在步骤 2 中您已经向 Sql Server 注册了程序集。
I know this is a very old question now, but I have recently found a way to achieve what you want. When you try and using
Assembly.Load(...)
in a SQL CLR hosted assembly, it will explicitly fail, this is by design, even withPERMISSION_SET = UNSAFE
. This is to ensure the stability of the database server.The technique to loading your dynamic assemblies, is to register them first and then resolve the type using
Type.GetType(...)
passing in the fully qualified type name (including assembly version information.Here are the steps:
1.Compile the type, and finalise on disk (i.e. do not create in-memory assemblies). The
CompilerResults
type will have aCompiledAssembly
property andPathToCompiledAssembly
property. Use the latter as accessing theCompiledAssembly
property will attempt to useAssembly.Load
.2.Using the path, I call a stored procedure from my code (using
new SqlConnection("Context Connection = true")
) which I pass in the name of the assembly (which I have predetermined) and the compiled assembly path:3.Using your predetermined name, you can use
Type.GetType(...)
, e.g.:When the SQLCLR attempts to resolve the type, it should find it, because in step 2 you've already registered the assembly with Sql Server.
我猜当您执行 CREATE ASSEMBLY 时,您已将 PERMISSION_SET 设置为 SAFE (如果您未指定它,这将是默认值)。如果您想执行此操作,则需要将其更改为 EXTERNAL_ACCESS 或 UNSAFE。
http://msdn.microsoft.com/en-us/library/ms189524。 ASPX
I'm guessing you've got the PERMISSION_SET set to SAFE when you did CREATE ASSEMBLY (this will be the default if you didn't specify it). You'll need to change it to EXTERNAL_ACCESS or UNSAFE if you want to do this.
http://msdn.microsoft.com/en-us/library/ms189524.aspx
我是 Microsoft 的开发人员之一,致力于 SQL-CLR 集成,所以我也许能提供帮助。
要实现您想要的效果,您需要做两件事:
请注意,执行所有这些操作会产生一些负面影响:
如果可能的话,请考虑重新设计您的应用程序,以便将所有需要的程序集预先加载到数据库本身中。
[编辑:如果以上都没有帮助,最好在 MSDN 论坛上提问]。
I was one the developers @ Microsoft who worked on SQL-CLR integration, so I may be able to help.
To achieve what you want you need to do two things:
Note that doing all those things has several negative side-effects:
If at all possible, consider redesigning your app so that all needed assemblies are pre-loaded into the database itself.
[EDIT: if none of the above helps it best to ask on MSDN forums].