如何在DACPAC发布时排除登录账号的默认数据库设置?
我使用PowerShell脚本调用SQLPackage.exe从QA数据库提取Dacpac文件,发布到本地SQL Server Express时遭遇部署失败:脚本尝试创建域登录账号Domain\sg.AllApplicationDevelopers,但指定的默认数据库ESIncome在本地服务器不存在。需求是保留用户/登录对象的同时,避免因不存在的默认数据库导致报错。
错误信息
Could not deploy package.
Error SQL72014: Core Microsoft SqlClient Data Provider: Msg 15010, Level 16, State 1, Line 1 The database 'ESIncome' does not exist. Supply a valid database name. To see available databases, use sys.databases.
Error SQL72045: Script execution error. The executed script:
CREATE LOGIN [Domain\sg.AllApplicationDevelopers]
FROM WINDOWS WITH DEFAULT_DATABASE = [ESIncome], DEFAULT_LANGUAGE = [us_english];
原PowerShell脚本
$dacpacFile = "eServices.dacpac" $sourceServer = "STG-SQL01" $sourceDatabase = "eServices" $targetServer = "localhost\SQLEXPRESS" $targetDatabase = "eServices" $sqlpackage = "C:\Users\<username>\.dotnet\tools\sqlpackage.exe" Write-Host "Generating Dacpac file..." -ForegroundColor Green $sourceConnectionString = "Server=$sourceServer;Database=$sourceDatabase;Encrypt=False; Integrated Security=SSPI;" $arguments = "/Action:""Extract""", "/SourceConnectionString:""$sourceConnectionString""", "/TargetFile:""./$dacpacFile""" $arguments & $sqlpackage $arguments if($(Write-Host "Publish to '$targetServer'? Y / N: " -NoNewline -ForegroundColor Green; Read-Host) -eq 'y') { Write-Host "Applying file to target db..." -ForegroundColor Green $targetConnectionString = "Server=$targetServer;Database=$targetDatabase;Encrypt=False; Integrated Security=SSPI;" $arguments = "/Action:Publish", "/SourceFile:""./$dacpacFile""", "/TargetConnectionString:""$targetConnectionString""", "/p:IncludeCompositeObjects=True" & $sqlpackage $arguments }
解决方案
方法1:发布时跳过默认数据库配置
在发布命令中添加/p:DeployDatabaseLoginDefaults=False参数,该参数会让SQLPackage在创建登录时不使用源数据库的默认数据库设置,转而使用SQL Server的系统默认数据库(通常为master)。
修改后的发布参数代码:
$arguments = "/Action:Publish", "/SourceFile:""./$dacpacFile""", "/TargetConnectionString:""$targetConnectionString""", "/p:IncludeCompositeObjects=True", "/p:DeployDatabaseLoginDefaults=False"
方法2:提取Dacpac时移除默认数据库属性
如果希望从源数据库提取时就不包含登录账号的默认数据库信息,可在提取命令中添加/p:IgnoreLoginDefaultDatabase=True参数,生成的Dacpac将不会携带默认数据库配置。
修改后的提取参数代码:
$arguments = "/Action:""Extract""", "/SourceConnectionString:""$sourceConnectionString""", "/TargetFile:""./$dacpacFile""", "/p:IgnoreLoginDefaultDatabase=True"
方法3:通过部署配置文件自定义行为
创建一个.publish.xml配置文件,在其中定义部署规则,适合需要复用复杂配置的场景。
配置文件示例(CustomPublishProfile.publish.xml):
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <TargetDatabaseName>eServices</TargetDatabaseName> <DeployDatabaseLoginDefaults>False</DeployDatabaseLoginDefaults> <IncludeCompositeObjects>True</IncludeCompositeObjects> </PropertyGroup> </Project>
修改后的发布命令参数:
$arguments = "/Action:Publish", "/SourceFile:""./$dacpacFile""", "/TargetConnectionString:""$targetConnectionString""", "/p:IncludeCompositeObjects=True", "/Profile:""./CustomPublishProfile.publish.xml"""
方案对比
- 方法1:无需修改提取流程,直接在发布阶段调整,适合临时适配目标环境的场景。
- 方法2:从源头上清除默认数据库信息,生成的Dacpac通用性更强,适配多目标环境。
- 方法3:便于保存和复用复杂部署规则,适合团队协作或标准化部署流程。
内容的提问来源于stack exchange,提问作者USMC6072

