3

我们正在使用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();
}
4

1 回答 1

2

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

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

不过需要注意两点:1) 生成的脚本必须从中执行SQLCMD(例如,您不能只使用 C#SqlConnection甚至 SMO执行它ServerConnection),2) 我建议如果您手动将脚本包装在事务中,您跳过设置IncludeTransactionalScripts为的步骤true

于 2016-02-04T21:34:32.897 回答