我们有一个具有创建用户脚本的 DACPAC。用户有一个登录需要设置为 Windows 域用户当我们为测试/暂存/发布进行构建时,我们需要能够为用户登录应用不同的域和用户。
我以为我们可以使用 SQLCMD 变量,但在尝试使用此脚本时出现 SQL71501 错误该脚本如下所示:
CREATE USER [Username]
For Login [$(SQLLoginDomain)]
WITH DEFAULT_SCHEMA = [SCHEMANAME]
GO
我们有一个具有创建用户脚本的 DACPAC。用户有一个登录需要设置为 Windows 域用户当我们为测试/暂存/发布进行构建时,我们需要能够为用户登录应用不同的域和用户。
我以为我们可以使用 SQLCMD 变量,但在尝试使用此脚本时出现 SQL71501 错误该脚本如下所示:
CREATE USER [Username]
For Login [$(SQLLoginDomain)]
WITH DEFAULT_SCHEMA = [SCHEMANAME]
GO
基于痛苦的经验,我的建议是将任何特定于环境的东西排除在 SQL Server 数据库项目之外。相反,在部署 DACPAC 后,将任何特定于环境的内容(权限等)应用为单独的 T-SQL 脚本。如果您使用发布管理执行此操作,我有一个简单的博客系列,其中包括在此处发布 DACPAC 和单独的权限脚本。有关应用标记化权限脚本的帖子在此处。
我们最终通过在 dacpac 中使用部署后脚本解决了这个问题,只要您在尝试调用用户之前进行检查以查看他们是否已经存在,这一切都可以正常工作,因为这是您可以使用它们的唯一地方部署脚本。
您可以从sys.dm_exec_sessions系统视图中读取 Windows 域。
例如,您可以在 DACPAC 的部署后脚本中添加这样的内容...
DECLARE @host_name nvarchar(128);
DECLARE @nt_domain nvarchar(128);
SELECT
@host_name = host_name,
@nt_domain = nt_domain
FROM
sys.dm_exec_sessions
WHERE
session_id = @@SPID;
-- If the domain is present, setup the login/user.
-- Otherwise, we are probably running under test environment, so we can skip this.
-- `@nt_domain = @host_name` tends to hold for LocalDB.
IF @nt_domain IS NOT NULL AND @nt_domain <> @host_name BEGIN
DECLARE @user_nonquoted nvarchar(128) = @nt_domain + '\YourUserName';
DECLARE @user nvarchar(128) = QUOTENAME(@user_nonquoted);
IF @user_nonquoted NOT IN (SELECT name FROM sys.database_principals)
EXEC ('CREATE LOGIN ' + @user + ' FROM WINDOWS');
IF @user_nonquoted NOT IN (SELECT name FROM sys.server_principals)
EXEC ('CREATE USER ' + @user + ' FOR LOGIN ' + @user);
END