C# 具有CLR函数的System.Security.SecurityException

C# 具有CLR函数的System.Security.SecurityException,c#,sql-server,sqlclr,C#,Sql Server,Sqlclr,首先,我要说这个问题与我们有关 不过,我会把所有的东西移到这里作为参考 我遇到的问题是,我仍然会遇到错误: Msg 6522,16级,状态1,程序PerfInsert,第0行[批处理起始行31] 在执行用户定义例程或聚合“PerfInsert”期间发生.NET Framework错误: System.Security.SecurityException:请求失败。 System.Security.SecurityException: 在MiddleMan.MiddleMan.CreateComm

首先,我要说这个问题与我们有关

不过,我会把所有的东西移到这里作为参考

我遇到的问题是,我仍然会遇到错误:

Msg 6522,16级,状态1,程序PerfInsert,第0行[批处理起始行31] 在执行用户定义例程或聚合“PerfInsert”期间发生.NET Framework错误: System.Security.SecurityException:请求失败。 System.Security.SecurityException: 在MiddleMan.MiddleMan.CreateCommand(SqlString tblString、SqlString featureName、SqlString connectionString、SqlString perfionConnectionString、SqlString日志文件)

尽管我相信我已经遵循了所有必要的步骤来正确设置它。我甚至还验证了SQL Server是否具有文件目录的权限

有人知道我还能查到什么来确定丢失的部分吗

或者我需要将其设置为“不安全”的程序集吗

C#代码:

SQL代码:


您正在使用多线程,因此是的,程序集100%需要具有
权限\u SET=safe

此外,由于您已经设置了非对称密钥和关联的登录名(感谢您这样做并且没有使用),因此在将程序集设置为不安全之前,您需要执行以下操作:

使用[master];
将不安全装配授予[BrokcRetail];
然后:

使用[{db_-containing_-assembly_-not_-master];
更改程序集[PerfInsert],权限设置为不安全;
或者,如果您创建基于非对称密钥的登录并首先授予它
不安全程序集
权限,那么您可以简单地在
创建程序集
语句中使用
不安全
,而不是
安全

从SQL Server 2017开始,您需要在创建程序集之前创建非对称密钥和关联的登录名。非对称密钥和登录名进入
[master]
,而程序集可以进入任何数据库(包括
[master]
,但通常最好不要将自定义代码放入其中)

如果您已经在使用SQL Server 2017或更高版本,并且问题中显示的代码与实际执行顺序一致,那么我猜您已经将数据库设置为上的可信或禁用了“CLR strict security”。否则,如果没有先创建基于签名的登录名并授予
不安全程序集
权限,您就根本无法创建程序集。如果我没有记错,您可以重新启用该数据库的“CLR strict security”和/或关闭
Trustly

另外,正如我在您的相关问题(本问题中链接的问题)上所指出的,您应该使用
SqlString
而不是
SqlChars
SqlString.Value
返回.NET
string
,而
SqlChars.Value
返回
char[]
。很久以前,人们将
SqlChars
NVARCHAR(MAX)
关联,将
SqlString
NVARCHAR(1-4000)关联
,但这只是因为Visual Studio/SSDT在生成DDL以发布数据库项目时将这些映射用作默认值。但它们之间从来没有任何技术/字符串映射。您可以将.NET类型与T-SQL数据类型一起使用

另外,在SQLCLR中使用多线程时,请谨慎(并进行大量测试)

有关使用SQLCLR的更多信息,请访问

相关帖子:

  • (在DBA.StackExchange上)

  • 启动随机外部进程绝对不安全。这段代码的意义何在?您可以从SQL Server代理作业执行外部程序。如果您放松安全性,您可以使用
    xp\u cmd
    ,但是,当代理可以在不放松安全性的情况下执行相同操作时,为什么要这样做?这看起来像是一个更好解决问题的经典案例d与运行或启动所需代码的客户端应用程序一起运行。如果您需要能够从数据库端随意触发它,则可以设置Service Broker队列并等待请求。在SQL Server上下文下启动任意进程是一个安全噩梦。您必须使用外部访问或不安全,代码才能运行在SQL Server服务帐户下。这不是一个好主意。无论你想做什么,你都不需要使用SQLCLR来做,更不用说允许不安全的代码执行了。好吧,你肯定需要一个
    不安全的
    程序集——如果你使用SQL Server 2017,你会遇到(作者是同一个善良的灵魂,他回答了你的另一个问题,他很可能也会突然出现在这个问题上)。@PanagiotisKanavos我当然同意,不幸的是,微软让SQLCLR支持萎靡不振,这是令人沮丧的,离理想还很远。但是,我不同意“不完美==不可行”的观点。该功能存在,并且在许多情况下都能正常工作,因此我认为使用它不会出现总体问题。当然,这个特定的实现可能是不明智的,最好通过
    xp\u cmdshell
    或SQL代理作业来实现。但是,这与SQLCLR一般无关。您不喜欢或不使用它没关系,但也没那么糟糕正如你所描绘的。你不希望你能得到一个
    ReadOnlySpan
    而不是一个SqlString作为输入,这样你就可以不用担心临时字符串了吗?@SolomonRutsky再次感谢你的帮助。我让一切都正常了,并决定按照你先前建议的方式实现它。我只想至少得到一个如果我真的使用此方法,所有活动部件都已正确组装。再次感谢您的帮助!@DougCoats欢迎您。很高兴我能提供帮助。请澄清,我最初建议采用哪种方式?通过SQL代理进行计划,或使用单独的Express实例
    using Microsoft.SqlServer.Server;
    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Data.SqlTypes;
    using System.Diagnostics;
    
        namespace MiddleMan
    {
        public static class MiddleMan
        {
            [SqlProcedure(Name = "PerfInsert")]
            public static SqlInt32 CreateCommand(SqlString tblString, SqlString featureName, SqlString connectionString, SqlString perfionConnectionString, SqlString logFile)
            {
                Process compiler = new Process();
                compiler.StartInfo.FileName = "C:\\SQL Server C# Functions\\PerfionLoader\\PerfionLoader\\bin\\Release\\PerfionLoader.exe";
                compiler.StartInfo.Arguments = tblString.Value + " " + featureName.Value + " " + connectionString.Value + " " + perfionConnectionString.Value + " " + logFile.Value;
                //compiler.StartInfo.UseShellExecute = false;
                //compiler.StartInfo.RedirectStandardOutput = true;
                compiler.Start();
                return SqlInt32.Zero;
            }
        }
    }
    
    CREATE ASSEMBLY PerfInsert
        AUTHORIZATION dbo
        FROM '\\bk-int-1\c$\SQL Server C# Functions\MiddleMan\MiddleMan\bin\Release\MiddleMan.dll'
        WITH PERMISSION_SET = SAFE
    GO
    
    
    CREATE ASYMMETRIC KEY [Brock.Retail_Brock.Retail_Brock]
      AUTHORIZATION [dbo]
      FROM EXECUTABLE FILE = '\\bk-int-1\c$\SQL Server C# Functions\MiddleMan\MiddleMan\bin\Release\MiddleMan.dll';
    
      CREATE LOGIN BrokcRetail
        FROM ASYMMETRIC KEY [Brock.Retail_Brock.Retail_Brock]
    
    
    CREATE PROCEDURE PerfInsert
        (
            @tblString nvarchar(max)
            , @featureName nvarchar(max)
            , @connectionString nvarchar(max)
            , @perfionConnectionString nvarchar(max)
            , @logFiel nvarchar(max)
        )
        AS EXTERNAL NAME PerfInsert.[MiddleMan.MiddleMan].[CreateCommand]
    GO