创建程序集失败,因为方法不可见 - 但一切都是 public
Create Assembly fails because methods are not visible - but everything is public
我正在尝试将曾经是一个大型数据库项目的 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*/}
}
}
这些方法是 public,我正在使用程序集属性使它们更加可见。有什么我想念的吗?
一个明确的问题是构造函数方法 -- CmsSelectQueryStoredProcedure()
-- 不能/永远不会被调用,因为它是一个实例方法,并且这些 classes 永远不会被实例化。您需要使用以下形式的静态构造函数:
static CmsSelectQueryStoredProcedure()
{
_cmsDataService = new CmsDataService();
}
另一部分可能是 SqlProcedure
的方法属性可能需要包含括号。意思是,使用这个:
[SqlProcedure()]
而不是这个:
[SqlProcedure]
另外,输入参数/输出参数最好使用Sql*
类型/SQLCLR方法使用return类型。意思是,使用 SqlString
而不是常规的 C# string
.
public static void ExecuteCmsSelectQuery(SqlString targetGroup, SqlString query, SqlString targetGroupUserName, SqlString targetGroupPassword)
然后通过 .Value
属性 访问该参数的 .NET 类型,它们都有:
targetGroup.Value
还有,你真的需要静态变量吗?这将要求 Assembly 被标记为 UNSAFE
除非它也被声明为 readonly
.
此限制有充分的理由:每个程序集所有者的每个数据库有一个 AppDomain。这意味着,同时调用此代码的所有会话都将访问该(或任何)静态变量的完全相同的引用。执行上下文不是每个会话,而是同时在所有会话之间共享。
另外,命名空间名称本身可能是个问题。我通常从不为 SQLCLR 代码使用命名空间,因为它们需要嵌入到 CREATE 对象语句的 AS EXTERNAL NAME
子句的 class 名称部分。例如,我猜你的存储过程最终会是:
[MyAssembly].[KK.Corporate.ServerGroupQuery.Database.Programmability.Stored_Procedures.CmsSelectQueryStoredProcedure].[ExecuteCmsSelectQuery]
我还没有尝试过那个长度或多个句点和下划线,所以可能没问题。
有关使用 SQLCLR 的更多信息,请参阅我在 SQL Server Central 上就此主题撰写的系列文章(阅读该站点上的文章需要免费注册;我无法控制该政策):
我正在尝试将曾经是一个大型数据库项目的 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*/}
}
}
这些方法是 public,我正在使用程序集属性使它们更加可见。有什么我想念的吗?
一个明确的问题是构造函数方法 -- CmsSelectQueryStoredProcedure()
-- 不能/永远不会被调用,因为它是一个实例方法,并且这些 classes 永远不会被实例化。您需要使用以下形式的静态构造函数:
static CmsSelectQueryStoredProcedure()
{
_cmsDataService = new CmsDataService();
}
另一部分可能是 SqlProcedure
的方法属性可能需要包含括号。意思是,使用这个:
[SqlProcedure()]
而不是这个:
[SqlProcedure]
另外,输入参数/输出参数最好使用Sql*
类型/SQLCLR方法使用return类型。意思是,使用 SqlString
而不是常规的 C# string
.
public static void ExecuteCmsSelectQuery(SqlString targetGroup, SqlString query, SqlString targetGroupUserName, SqlString targetGroupPassword)
然后通过 .Value
属性 访问该参数的 .NET 类型,它们都有:
targetGroup.Value
还有,你真的需要静态变量吗?这将要求 Assembly 被标记为 UNSAFE
除非它也被声明为 readonly
.
此限制有充分的理由:每个程序集所有者的每个数据库有一个 AppDomain。这意味着,同时调用此代码的所有会话都将访问该(或任何)静态变量的完全相同的引用。执行上下文不是每个会话,而是同时在所有会话之间共享。
另外,命名空间名称本身可能是个问题。我通常从不为 SQLCLR 代码使用命名空间,因为它们需要嵌入到 CREATE 对象语句的 AS EXTERNAL NAME
子句的 class 名称部分。例如,我猜你的存储过程最终会是:
[MyAssembly].[KK.Corporate.ServerGroupQuery.Database.Programmability.Stored_Procedures.CmsSelectQueryStoredProcedure].[ExecuteCmsSelectQuery]
我还没有尝试过那个长度或多个句点和下划线,所以可能没问题。
有关使用 SQLCLR 的更多信息,请参阅我在 SQL Server Central 上就此主题撰写的系列文章(阅读该站点上的文章需要免费注册;我无法控制该政策):