如果新约束验证失败,则 DacServices 回滚
DacServices Rollback if new constraint validation fails
我们正在使用 DacServices
更新我们的数据库。然而,有时添加新的约束会导致 Constraint Violations,这需要我们编写迁移脚本以确保列中的数据有效。
但是如果 DacServices.Deploy
选项为 true 并且新约束错误,我不知道如何回滚 DacServices 所做的更改。
我们正在使用 AlwaysOn 可用性,因此执行 backup/restore 将非常困难。以下是我尝试过但没有成功的一种方法。
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();
}
正如 OP 指出的那样,这里的问题是验证新约束的步骤发生在外部 IncludeTransactionalScripts
时包含的事务语句是设置为 true
。这意味着将提交对数据库的更改,即使部署指定的约束与数据库中的数据不一致。这似乎是 Microsoft 应该修复的错误。
尽管如此,我的建议是使用 DacServices
框架生成部署 脚本 ,而不是直接部署到数据库。生成脚本后,您可以添加事务语句以确保脚本的 entirety 作为原子事务执行。您可以在 USE [$(DatabaseName)]; GO
语句之后插入一个 BEGIN TRANSACTION
语句,然后在脚本的最后插入一个 COMMIT TRANSACTION
语句。
但有两点需要注意:1) 生成的脚本 必须 从 SQLCMD
执行(您不能仅使用 C# SqlConnection
甚至 SMO ServerConnection
例如),2) 我建议如果您手动将脚本包装在事务中,则跳过将 IncludeTransactionalScripts
设置为 true
的步骤。
我们正在使用 DacServices
更新我们的数据库。然而,有时添加新的约束会导致 Constraint Violations,这需要我们编写迁移脚本以确保列中的数据有效。
但是如果 DacServices.Deploy
选项为 true 并且新约束错误,我不知道如何回滚 DacServices 所做的更改。
我们正在使用 AlwaysOn 可用性,因此执行 backup/restore 将非常困难。以下是我尝试过但没有成功的一种方法。
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();
}
正如 OP 指出的那样,这里的问题是验证新约束的步骤发生在外部 IncludeTransactionalScripts
时包含的事务语句是设置为 true
。这意味着将提交对数据库的更改,即使部署指定的约束与数据库中的数据不一致。这似乎是 Microsoft 应该修复的错误。
尽管如此,我的建议是使用 DacServices
框架生成部署 脚本 ,而不是直接部署到数据库。生成脚本后,您可以添加事务语句以确保脚本的 entirety 作为原子事务执行。您可以在 USE [$(DatabaseName)]; GO
语句之后插入一个 BEGIN TRANSACTION
语句,然后在脚本的最后插入一个 COMMIT TRANSACTION
语句。
但有两点需要注意:1) 生成的脚本 必须 从 SQLCMD
执行(您不能仅使用 C# SqlConnection
甚至 SMO ServerConnection
例如),2) 我建议如果您手动将脚本包装在事务中,则跳过将 IncludeTransactionalScripts
设置为 true
的步骤。