4

我从 CLR(.net 程序集)获得了一个 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()

这是我的 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

这是我的班级(大会)

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();
        }
    }
}
4

3 回答 3

6

问题只是您试图访问标记为的程序集中的外部资源SAFE。访问外部资源需要将 Assembly 设置为至少EXTERNAL_ACCESS(在某些情况下UNSAFE)。但是,查看您的代码,您只是尝试连接到本地实例,在这种情况下,有一种更简单(更快)的方法:使用"Context Connection = true;"ConnectionString。

上下文连接是与当前进程/会话的直接连接,有时也称为进程内连接。使用上下文连接的好处是:

  • 可以在标记为的程序集中完成SAFE
  • 访问本地临时对象(临时表和临时过程,两者的名称都以 single#而不是 double开头##
  • 访问SET CONTEXT_INFOCONTEXT_INFO()
  • 没有连接启动开销

还:

  • 无论您使用进程内连接、上下文连接还是常规/外部连接,都不需要使用正式请求权限SqlClientPermission
  • 您应该始终通过调用外部资源的方法来清理它们Dispose()。不是所有的对象都有这个,但是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);
      }
    }
  }
}
于 2015-09-01T21:16:48.780 回答
0

我只是想为此添加我的两种感觉。我正在做一些非常相似的事情,但我遇到了同样的错误。这是我发现的,但是 b/c 我没有这个级别的数据库访问权限,我无法测试它。

最简单的(虽然不是 MSDN 建议只让 CLR proc 运行)是将权限级别设置为 External_Access ...

SQL Server 主机策略级别权限集 SQL Server 主机策略级别授予程序集的代码访问安全权限集由创建程序集时指定的权限集确定。共有三个权限集:SAFE、EXTERNAL_ACCESS 和 UNSAFE。

权限级别在 CLR 项目的属性页上设置,数据库选项卡 - 设置权限级别 - 外部,设置 Aassembly Owner-dbo,然后运行 ​​tsql 'ALTER DATABASE DataBaseName SET TRUSTWORTHY ON' 这将完成工作!- 并且 SmtpClient 将可以正常工作...然后正确执行并使用强名称密钥文件对 Assenbly 进行签名...

全文在这里...

于 2012-06-19T19:33:53.830 回答
-4

您是否将 DB 设置为 Trusrtworth ON 并启用了 clr?

尝试这个

sp_configure 'clr enabled', 1
GO
RECONFIGURE
GO

ALTER DATABASE [YourDatabase] SET TRUSTWORTHY ON
GO

我在这里有一个关于如何使用可能有帮助的 CLR 存储过程的指南。

于 2010-11-07T19:37:24.600 回答