如果新约束验证失败,则DacServices回滚

时间:2016-02-02 18:51:50

标签: c# sql-server dac

我们正在使用DacServices更新我们的数据库。但是,有时会添加导致约束违规的新约束,这需要我们编写迁移脚本以确保列中的数据有效。

但是DacServices.Deploy如果ScriptNewConstraintValidation选项为true且新约束错误,我无法弄清楚如何回滚DacServices所做的更改。

我们正在使用AlwaysOn可用性,因此执行备份/恢复将非常困难。以下是我尝试过的一种方法,但没有成功。

var dacServices = new DacServices(dbConnection.ConnectionString);
var deploymentOptions = new DacDeployOptions
{
    CreateNewDatabase = createNewDatabase,
    ScriptDatabaseCompatibility = false,
    ScriptDatabaseCollation = false,
    IgnoreUserSettingsObjects = true,
    DropPermissionsNotInSource = false,
    DropRoleMembersNotInSource = false,
    IgnorePermissions = true,
    IgnoreRoleMembership = true,
    GenerateSmartDefaults = true,
    IncludeTransactionalScripts = true,
    ScriptNewConstraintValidation = true
};

Microsoft.SqlServer.Dac.DacPackage dacPackage = DacPackage.Load(dacPath);

Console.WriteLine("Deploying DacPac");
CancellationTokenSource tokenSource = new CancellationTokenSource();
try
{
    dacServices.Deploy(dacPackage, databaseName, true, deploymentOptions, tokenSource.Token);
}
catch(Exception)
{
    tokenSource.Cancel();
}

1 个答案:

答案 0 :(得分:2)

正如OP指出的那样,问题在于验证新约束的步骤发生在IncludeTransactionalScripts设置为{{1}时包含的事务语句的外部 }}。这意味着即使部署指定了与数据库中的数据不一致的约束,也将提交对数据库的更改。这似乎是微软应该修复的错误。

尽管如此,我的建议是使用true框架生成部署脚本,而不是直接部署到数据库。生成脚本后,您可以添加事务语句以确保脚本的 complete 作为原子事务执行。您可以在DacServices语句之后插入BEGIN TRANSACTION语句,然后在脚本的最后插入USE [$(DatabaseName)]; GO语句。

有两点需要注意:1)生成的脚本必须COMMIT TRANSACTION执行(您无法使用C#SQLCMD执行此操作甚至是SMO SqlConnection,例如),2)我建议如果您在事务中手动包装脚本,则跳过将ServerConnection设置为IncludeTransactionalScripts的步骤。