创建程序集失败,因为方法不可见,但所有内容都是公共的

本文关键字:因为 失败 程序集 方法 创建 | 更新日期: 2023-09-27 18:26:17

我正在尝试将一个CLR存储过程重新配置为一个核心逻辑项目和一个数据库项目,以分离我的顾虑。所以项目的架构是这样的:

  'src
     'Company.Core
         'CoreCode.cs
         'CoreCode2.cs
     'Company.Database
         'Programmability'Stored Procedures
             CmsSelectQueryStoredProcedure.cs
             ClrStoredProcedure2.cs

当我尝试部署该项目时,我会收到一系列错误消息:

CREATE ASSEMBLY for assembly 'MyAssembly' failed because assembly "MyAssembly" failed 
verification. Check it the referenced assemblies are up-to-date and trusted (for 
external_access or unsafe) to execute in the database. CLR verifier error messages if any 
will follow this message.
MyAssembly.Programmability.Stored_Procedures.CmsSelectQueryStoredProcedure::.ctor Method is 
not visible.
MyAssembly.Programmability.Stored_Procedures.CmsSelectQueryStoredProcedure::
.ExecuteCmsSelectQuery Method is not visible.
(Many more of these)

ClrStoredProcedure1.cs包含以下代码:

using System;
using System.Data.SqlClient;
using System.Security;
using Company.Core;
using Microsoft.SqlServer.Server;

[assembly: AllowPartiallyTrustedCallers(PartialTrustVisibilityLevel = PartialTrustVisibilityLevel.VisibleToAllHosts)]

namespace KK.Corporate.ServerGroupQuery.Database.Programmability.Stored_Procedures
{
    public class CmsSelectQueryStoredProcedure
    {
        public static CmsDataService _cmsDataService;
        public CmsSelectQueryStoredProcedure()
        {
            _cmsDataService = new CmsDataService();
        }
        const string InitialCatalog = "master";
        const int ConnectTimeout = 10;
        [SqlProcedure]
        public static void ExecuteCmsSelectQuery(string targetGroup, string query, string targetGroupUserName, string targetGroupPassword)
        {/*etc*/}
    }
}

这些方法是公共的,我使用assembly属性使它们更加可见。我缺了什么吗?

创建程序集失败,因为方法不可见,但所有内容都是公共的

一个明确的问题是构造函数方法CmsSelectQueryStoredProcedure()永远不能/永远不会被调用,因为它是一个实例方法,并且这些类永远不会被实例化。您需要使用以下形式的静态构造函数:

    static CmsSelectQueryStoredProcedure()
    {
        _cmsDataService = new CmsDataService();
    }

另一点可能是SqlProcedure的方法属性可能需要包含括号。意思是,使用这个:

[SqlProcedure()]

而不是这个:

[SqlProcedure]

此外,最好将Sql*类型用于SQLCLR方法的输入参数/输出参数/返回类型。也就是说,使用SqlString而不是常规的C#string

public static void ExecuteCmsSelectQuery(SqlString targetGroup, SqlString query, SqlString targetGroupUserName, SqlString targetGroupPassword)

然后通过它们都具有的.Value属性访问该参数的.NET类型:

targetGroup.Value

另外,你真的需要一个静态变量吗?这将要求程序集标记为UNSAFE,除非它也声明为readonly

这个限制有充分的理由:每个程序集所有者每个数据库有一个AppDomain。也就是说,所有同时调用此代码的会话都将访问该(或任何)静态变量的完全相同的引用。执行上下文不是每个会话的,而是同时在所有会话之间共享的。


此外,命名空间名称本身可能是个问题。我通常从不为SQLCLR代码使用名称空间,因为它们需要嵌入CREATE对象语句的AS EXTERNAL NAME子句的类名部分。例如,我猜测您的存储过程最终会是:

[MyAssembly].[KK.Corporate.ServerGroupQuery.Database.Programmability.Stored_Procedures.CmsSelectQueryStoredProcedure].[ExecuteCmsSelectQuery]

我还没有尝试过这种长度,也没有尝试过使用多个句点和下划线,所以可能还不错。


有关使用SQLCLR的更多信息,请参阅我在SQL Server Central上就此主题撰写的一系列文章(阅读该网站上的文章需要免费注册;我无法控制该策略):

通往SQLCLR 的阶梯

相关文章: