Is there any way of preventing users being dropped when publishing a DACPAC using SqlPackage.exe, other than changing the setting below, which prevents all objects from being dropped if they're not in the DACPAC.
<DropObjectsNotInSource>True</DropObjectsNotInSource>
We deploy to a number of environments, each with different users. Current workarounds are to either:
/Action:Script
and manually change the deployment script. Neither of these are ideal though...
A simple command would be "sqlpackage /a:publish /sf:db1. dacpac /tsn:localhost /tdn:db1" to publish dacpac "db1" to a database "localhost\db1". For other publish options type "sqlpackage /a:publish /?" to get the list of applicable actions on the command line.
SqlPackage.exe is a command-line utility that automates the following database development tasks by exposing some of the public Data-Tier Application Framework (DacFx) APIs: Version: Returns the build number of the SqlPackage application.
The DAC package is in turn deployed to a test, staging or production database through an automated process or manually with a CLI or GUI tool. The . dacpac can be used to update a database with new or modified objects, to revert to a previous version of the database, or to provision an entirely new database.
It is to be noted that DACPAC does not contain DATA and other server-level objects. The file can contains all object types which might be kept in SSDT project.
Use SqlPackage.exe parameters (since February 2015 release: New Advanced Publish Options to Specify Object Types to Exclude or Not Drop):
Here's the actual parameters we use in our deployment:
/p:DropObjectsNotInSource=True
/p:ExcludeObjectTypes=Users;Logins;RoleMembership;Permissions
The first line cleans all, but the next line further refines what not to drop. This combination proved the most effective with us to drop all unnecessary objects, yet retain the login mappings as they were.
Detailed documentation of all the parameters and their possible values can be found from MSDN - SqlPackage.exe
I ran into the same issue and used Pre/Post deployment scripts to reinsert users, permissions, roles, etc like the suggested blog post. However this became unmaintainable in the long run (users unable to authenticate during deployment, if the deployment fails permissions are not restored, security changes require going through source control and re-deployment).
Recently, I reevaluated the problem as we were migrating our deployment platform. With the DacFx API (and bug fixes) released, I was able to extend the deployment process in SSDT by creating a DeploymentPlanModifier. They provide an example for filtering objects on creation, with simple modifications I filter any drops for permission based object types (using /p:AdditionalDeploymentContributors argument).
[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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With