Juv*_*vil 4 t-sql sql-server sqlclr database-permissions
我从CLR(.net Assembly)获得了一个sql过程,当执行时返回错误
Msg 6522, Level 16, State 1, Procedure sp_HelloWorld, Line 0
A .NET Framework error occurred during execution of user defined routine or aggregate 'sp_HelloWorld':
System.Security.SecurityException: Request for the permission of type 'System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
System.Security.SecurityException:
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.PermissionSet.Demand()
at System.Data.Common.DbConnectionOptions.DemandPermission()
at System.Data.SqlClient.SqlConnection.PermissionDemand()
at System.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()
at HelloWorld.SQLCLR.HelloWorld()
Run Code Online (Sandbox Code Playgroud)
这是我的SQL脚本
go
drop procedure HelloWorld
drop assembly HelloWorld
GO
create assembly HelloWorld from 'F:\HelloWorld.dll'
with permission_set = safe
Go
create procedure sp_HelloWorld
as external name HelloWorld.[HelloWorld.SQLCLR].HelloWorld
go
exec sp_HelloWorld
Run Code Online (Sandbox Code Playgroud)
这是我的班级(大会)
using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
using System.Data.SqlClient;
using System.Security.Permissions;
using System.Data;
namespace HelloWorld
{
public class SQLCLR
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void HelloWorld()
{
string connectString1 = @"Data Source=localhost;Initial Catalog=ItemData;Integrated Security=True";
SqlClientPermission permission = new SqlClientPermission(PermissionState.None);
permission.Add(connectString1, "", KeyRestrictionBehavior.AllowOnly);
permission.PermitOnly();
SqlConnection sqlcon = new SqlConnection(connectString1);
sqlcon.Open();
SqlCommand sqlcmd = new SqlCommand("SELECT Top 1 * FROM ItemData.dbo.Item", sqlcon);
SqlDataReader reader = sqlcmd.ExecuteReader();
SqlContext.Pipe.Send(reader);
sqlcon.Close();
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题只是您尝试访问标记为的程序集中的外部资源SAFE.访问外部资源需要至少EXTERNAL_ACCESS(在某些情况下UNSAFE)设置程序集.但是,查看代码时,您只是尝试连接到本地实例,在这种情况下,有一种更容易(更快)的方法:使用"Context Connection = true;"ConnectionString.
Context Connection是与当前进程/会话的直接连接,有时也称为进程内连接.使用Context Connection的好处是:
SAFE#而不是双精度开头##)SET CONTEXT_INFO和CONTEXT_INFO()也:
SqlClientPermissionDispose()方法来清理外部资源.不是所有的对象都这样了,但是SqlConnection,SqlCommand和SqlDataReader肯定做.人们通常将一次性对象包装在一个using()块中,因为它是一个编译器宏,它扩展为try/finally结构,该结构调用该Dispose()方法finally以确保它被调用,即使发生错误也是如此.Dispose()许多/大多数一次性物品的方法自动处理调用Close(),所以你通常不需要调用Close()明确.您的代码应如下所示:
[Microsoft.SqlServer.Server.SqlProcedure]
public static void HelloWorld()
{
using (SqlConnection sqlcon = new SqlConnection("Context Connection = true;")
{
using (SqlCommand sqlcmd = new SqlCommand("SELECT Top 1 * FROM ItemData.dbo.Item",
sqlcon))
{
sqlcon.Open();
using (SqlDataReader reader = sqlcmd.ExecuteReader())
{
SqlContext.Pipe.Send(reader);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8409 次 |
| 最近记录: |