3

を使用してデータベースを更新していますDacServices。ただし、新しい制約が追加されて制約違反が発生する場合があり、列のデータが有効であることを確認するために移行スクリプトを作成する必要があります。

ただしDacServices.DeployScriptNewConstraintValidationオプションが true の場合と新しい制約エラーがあるため、DacServices によって行われた変更をロールバックする方法がわかりません。

AlwaysOn 可用性を使用しているため、バックアップ/復元の実行は非常に困難です。以下は、私が試みたが成功しなかった1つの方法です。

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 が指摘しているように、新しい制約を検証するステップが、が に設定されている場合に含まれるトランザクション ステートメントの外部で発生することです。これは、デプロイメントでデータベース内のデータと矛盾する制約が指定されていても、データベースへの変更がコミットされることを意味します。これは、Microsoft が修正すべきバグのようです。IncludeTransactionalScriptstrue

それにもかかわらず、私の提案は、データベースに直接デプロイするのではなく、フレームワークを使用してデプロイスクリプトDacServicesを生成することでした。スクリプトが生成されたら、トランザクション ステートメントを追加して、スクリプト全体がアトミック トランザクションとして実行されるようにすることができます。ステートメントの直後にステートメントを挿入し、スクリプトの最後にステートメントを挿入します。BEGIN TRANSACTIONUSE [$(DatabaseName)]; GOCOMMIT TRANSACTION

ただし、次の 2 つの点に注意してください。1) 生成されたスクリプトは、次から実行する必要SQLCMDがあります(たとえば、C#SqlConnectionや SMOServerConnectionを使用して実行することはできません)。2) トランザクションでスクリプトを手動でラップする場合は、に設定IncludeTransactionalScriptsする手順をスキップしますtrue

于 2016-02-04T21:34:32.897 に答える