将 Visual Studio 个数据库项目对象部署到 "dbo" 以外的模式

Deploy Visual Studio Database Project Objects to Schema other than "dbo"

我有以下场景。

我在 Visual Studio 数据库项目中有一个 SQLCLR 存储过程。这不应该在 dbo 架构中,而是在 foo 中。如我所见,在使用 Visual Studio 发布功能时,不可能为 SQLCLR 存储过程提供不同的模式。

所以我必须把它包起来。现在我有两个脚本。

一个要添加程序集:

CREATE ASSEMBLY [MyAssembly]
FROM 'MyAssembly.dll';
GO

还有一个是将存储过程添加到数据库:

CREATE PROCEDURE [foo].[MyProc](@param NVARCHAR(10))
    AS EXTERNAL NAME MyAssembly.ClassName.MyProc
GO

但现在由于对 MyAssembly 的未解析引用而出现错误。我认为这是因为它是同一个项目中的全部(SQLCLR 过程、T-SQL 包装过程、程序集添加脚本)并且它是对自身的引用。

在我自己的数据库架构下部署 SQLCLR 存储过程的最佳方法是什么?如果可以将其直接添加到 SQLCLR 实现中,那就太好了。

提前致谢。

我自己能解决吗。只是一个非常愚蠢的错误......

我的程序集名称具有 Company.Area.Technology.ProjectName 模式。如果我尝试用它创建一个存储过程,则会发生一个错误,需要一个点。

CREATE PROCEDURE [foo].[MyProc](@param NVARCHAR(10))
    AS EXTERNAL NAME Company.Area.Technology.ProjectName.ClassName.MyProc
GO

解决方法是将程序集名称设置在[].

之间
CREATE PROCEDURE [foo].[MyProc](@param NVARCHAR(10))
    AS EXTERNAL NAME [Company.Area.Technology.ProjectName].ClassName.MyProc
GO

这行得通。所以我可以将 CLR 过程包装到我自己的 Schema 中。

实际上,这应该不是问题。从 Visual Studio 2012 开始,有一个选项可以为 T-SQL 包装器对象设置架构。在项目属性中,转到 "Project Settings" 选项卡,在右侧的 "General" 部分下,有一个标记为:"Default schema" 的文本字段。这是用于 T-SQL 包装器对象的架构(我通常不使用 SSDT 部署,所以我只是在 Visual Studio 2015 年再次确认了这个信息 — 我知道,我知道,我 真的需要更新)。

这在我的回答中也提到了:Schema for CLR Stored Procedure During Deployment

如果您使用的 Visual Studio/SSDT 版本没有设置架构的选项 OR 如果您需要将对象放入多个模式,然后您应该能够简单地添加一个 T-SQL post-部署脚本,将对象移动到所需的模式。通过添加 T-SQL 脚本并将属性设置为 "post deployment"(或类似的东西),它将被插入到生成的发布脚本的末尾。

如果只是少数对象不会真正引入新对象,可以对每个对象做显式声明:

ALTER SCHEMA [foo] TRANSFER [dbo].[MyProc];

如果是大量的对象and/or偶尔会添加新的对象,你不想处理记得将它们添加到这个post-部署包含脚本,你可以循环浏览与该程序集关联的对象列表以创建一个动态 SQL 脚本,该脚本可以移动所有对象而无需任何东西,但程序集名称是硬编码的(技术上什至可以使用 MSBuild 动态/ SSDT 变量):

DECLARE @SQL NVARCHAR(MAX) = N'';

SELECT @SQL += N'ALTER SCHEMA [foo] TRANSFER [dbo].'
               + QUOTENAME(obj.[name]) + N';' + NCHAR(0x0D) + NCHAR(0x0A)
FROM   sys.assembly_modules amd
INNER JOIN sys.assemblies asm
        ON asm.[assembly_id] = amd.[assembly_id]
INNER JOIN sys.objects obj
        ON obj.[object_id] = amd.[object_id]
WHERE  asm.[name] = N'Company.Area.Technology.ProjectName' -- do not use [ and ] here
AND    SCHEMA_NAME(obj.[schema_id]) = N'dbo'

PRINT @SQL; -- DEBUG (else, comment out)

EXEC (@SQL);