5

我一直在使用 .dacpacs 将数据库更新部署到我们的各种环境中。我发现了一个导致特定更新发布失败的场景。

我需要添加一个新表dbo.Supplier并将一列添加到另一个dbo.PickZone具有引用新表的不可空外键的表中。SSDT 项目中的架构反映了这一点,为了准备新的 NOT NULL 列,我有以下预部署脚本;

IF object_id('dbo.Supplier') IS NULL
BEGIN
    CREATE TABLE [dbo].[Supplier]
    (
        [SupplierId] INT IDENTITY(1,1) NOT NULL,
        [Name] varchar(50) NOT NULL,
        CONSTRAINT [PK_Supplier] PRIMARY KEY CLUSTERED ([SupplierId])
    );

    SET IDENTITY_INSERT [dbo].[Supplier] ON;
    INSERT INTO Supplier (SupplierId, Name) VALUES (1, 'Default Supplier')
    SET IDENTITY_INSERT [dbo].[Supplier] OFF;

    ALTER TABLE dbo.PickZone ADD SupplierId int NULL;

    UPDATE PickZone SET SupplierId = 1

END

上面的脚本更新架构和数据,以确保在发布时(我正在使用 sqlpackage.exe)将外键约束应用于以下内容时不会失败dbo.PickZone.SupplierId

CREATE TABLE [dbo].[PickZone]
(
    [PickZoneId] INT IDENTITY (1, 1) NOT NULL PRIMARY KEY, 
    [Name] VARCHAR(50) NOT NULL,
    [SupplierId] INT NOT NULL,
    CONSTRAINT [FK_PickZone_Supplier] FOREIGN KEY ([SupplierId]) REFERENCES [dbo].[Supplier] ([SupplierId])
)

问题在于,似乎 vs2012 Publish 和 sqlpackage.exe deploy 都准备了所需的架构更新,然后执行预部署脚本,然后执行架构更新 - 由于预部署脚本制作架构,这些更新现在不同步变化。

这会导致架构发布再次尝试添加表和列,并导致它失败。

我显然可以更改我的部署过程以在 dacpac 部署之外执行这些类型的准备脚本,但我有点希望 dacpac 负责所有架构更改......

有谁知道让 dacpac 发布以适应此类更新的方法?

4

2 回答 2

2

我将描述我的解决方案。我们将使用部署 dacpacs 的 sqlpackage 工具。这个工具支持很多参数。其中之一是 GenerateSmartDefaults。见这里

我认为预部署脚本不一定包含架构修改。只有 SELECT、INSERT、UPDATE、DELETE 语句。部署后脚本也是如此。

  1. 修改您的数据库架构(添加不带默认值或作为外键的非空列)。
  2. 在部署后脚本中为此列添加 UPDATE 语句并构建 dacpac。
  3. 使用 SqlPackage 工具部署此 dacpac,如下所示: sqlpackage.exe /Action:Publish /SourceFile:your.dacpac /TargetServerName:serverName /TargetDatabaseName:databaseName /p:GenerateSmartDefaults=True
于 2015-06-23T08:47:54.900 回答
1

我认为您试图以错误的顺序执行此操作。默认情况下,SSDT 在整个更新完成之前不会检查约束 - 即使在部署后脚本之后也是如此。这意味着您应该能够在项目中添加具有默认值和约束的表,在 Post-Deploy 脚本中发出数据插入/更新,并在一切完成后让 SSDT 启用 FK 约束。

如果您对此不满意,您始终可以按以下顺序进行操作:

  • 创建表
  • 在部署后脚本中填充表
  • 快照该架构
  • -----------------
  • 添加列(默认)和 FK 约束
  • 快照该架构
  • -----------------
  • 发布快照 A
  • 发布快照 B

如果您的选项设置正确以在其他所有操作之后启用检查约束,我认为在大多数情况下您不必经历第二个过程。

于 2013-05-13T16:47:26.427 回答