使用SqlPackage.exe发布DACPAC时,如何防止用户被删除?

22

除了更改下面的设置以防止未包含在 DACPAC 中的所有对象被删除之外,是否有其他方法可以防止在使用 SqlPackage.exe 发布 DACPAC 时丢失用户?

<DropObjectsNotInSource>True</DropObjectsNotInSource>

我们会部署到多个环境,每个环境都有不同的用户。目前的解决方法要么是:

  1. 为每个环境编写用户脚本,在部署后重新创建用户
  2. 使用 /Action:Script 并手动更改部署脚本。

但是这些都不是理想的解决方法...

3个回答

22

使用 SqlPackage.exe 参数(自2015年2月发布以来:新的高级发布选项,用于指定要排除或不删除的对象类型):

以下是我们在部署中实际使用的参数:

/p:DropObjectsNotInSource=True 
/p:ExcludeObjectTypes=Users;Logins;RoleMembership;Permissions

第一行清理所有内容,但是下一行进一步细化了不应该删除的内容。对我们来说,这种组合证明了最有效的方法,可以删除所有不必要的对象,同时保留登录映射。

有关所有参数及其可能值的详细文档,请参阅MSDN - SqlPackage.exe


1
有时候我们需要排除以下内容:Credentials;DatabaseScopedCredentials - Jacob Foshee
我认为基于在项目文件中进行这些更改(实际上它被保存到.sqlproj.user文件中),它会被编译成dacpac文件。这不是事实吗?唯一的方法是将其作为SqlPackage.exe参数传递吗? - Joe Eng
没关系,我不知道你可以使用发布配置文件而不是参数。 - Joe Eng
1
请注意,如果您在PowerShell中运行此命令,则需要将对象类型列表放在引号中:/p:ExcludeObjectTypes="Users;Logins;RoleMembership;Permissions" - TabsNotSpaces

3
我遇到了同样的问题,并使用了预/后部署脚本来重新插入用户、权限、角色等,就像建议的博客文章一样。然而,长期来看,这种方法变得难以维护(在部署过程中无法验证用户身份,如果部署失败则无法恢复权限,安全更改需要通过源代码控制和重新部署进行)。
最近,我们正在迁移部署平台时,我重新评估了这个问题。使用发布的DacFx API(和错误修复),我能够通过创建一个DeploymentPlanModifier来扩展SSDT中的部署过程。他们提供了一个筛选创建对象的示例,通过简单的修改,我可以过滤任何基于权限的对象类型的删除操作(使用/p:AdditionalDeploymentContributors参数)。
[ExportDeploymentPlanModifier( UserMappingFilter.PlanFiltererContributorId, "1.0.0.0" )]
public class UserMappingFilter : DeploymentPlanModifier
{
    public const string PlanFiltererContributorId = "Dac.UserMappingFilter";

    protected override void OnExecute( DeploymentPlanContributorContext context )
    {
        DeploymentStep next = context.PlanHandle.Head;
        while( next != null )
        {
            DeploymentStep current = next;
            next = current.Next;

            DropElementStep dropStep = current as DropElementStep;
            if( dropStep != null && ShouldFilter( dropStep ) )
            {
                base.Remove( context.PlanHandle, dropStep );
            }
        }
    }

    private bool ShouldFilter( DropElementStep createStep )
    {
        TSqlObject target = createStep.TargetElement;


        if( target.ObjectType.Name == "RoleMembership" || target.ObjectType.Name == "User" || target.ObjectType.Name == "Role" )
        {
            return true;
        }


        return false;
    }
}

您能否请解释一下如何操作?我找不到安装/设置/其他方面的信息。我找到了一些需要创建 DLL 以通过 /p:AdditionalDeploymentContributors 参数传递的内容,但是我无法找到如何创建此 DLL。 - Dmitrij Kultasev
1
嘿,sidux - 你可以使用我为你预先制作的这个,或者以此为基础编写自己的代码:http://agilesqlclub.codeplex.com/(是我写的)- 更多细节请参见https://the.agilesql.club/Blogs/Ed-Elliott/HOWTO-Filter-Dacpac-Deployments。 - Ed Elliott
如何使用你自己的?我正在与Ed(agilesqlclub的作者)交流,但我们尚未使其正常工作。我正在使用VS2012 SSDT。主要问题是我不知道VS2012使用的SqlPackage.exe位于何处。我尝试了搜索和许多其他方法,但仍然没有效果。 - Dmitrij Kultasev

2
我们在部署后脚本中处理这个。它设置起来有点困难,但一旦设置好了,就可以为每个环境配置稍微不同的脚本。我们与发布配置文件一起使用,每个环境都有一个不同的配置文件。基本上,您使用PowerShell生成一堆用户和权限脚本,将这些脚本添加到您的项目中,然后在项目中包含这些文件。将博客文章中所称的“SecurityAdditionsWrapper.sql”添加到您的部署后脚本中,然后应该就可以了。只需删除项目中的其他安全性以确保其正确设置即可。

http://schottsql.blogspot.com/2013/05/ssdt-setting-different-permissions-per.html

SSDT 中还有以下选项: “删除源中不存在的权限” - False “删除没有在源中定义的角色成员” - False “忽略权限” - True “忽略角色成员” - True 我们使用这些选项,但是如果您需要更好地控制您的用户/权限以适应不同的环境,我强烈建议查看该博客文章。(特别感谢 Jamie Thomson 提出的原始想法。)

这个问题在MS Connect上有相关记录: https://connect.microsoft.com/SQLServer/feedback/details/775839/ssdt-add-publication-setting-to-ignore-database-users 尽管微软在2013年初将其标记为“不予修复”。 - Michael12345

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接