使用SSDT发布(.dacpac)部署非空外键架构更新

时间:2013-05-11 09:18:02

标签: sql-server-2008 visual-studio-2012 sql-server-data-tools dacpac

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

我需要添加一个新表dbo.Supplier并将列添加到另一个表dbo.PickZone,该表具有引用新表的不可为空的foriegn键。 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)在将foriegn键约束应用于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部署都准备了所需的架构更新,然后执行预部署脚本,然后执行架构更新 - 由于预部署,这些更新现在不同步脚本进行架构更改。

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

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

有没有人知道如何获得dacpac发布以满足此类更新的需要?

2 个答案:

答案 0 :(得分:2)

我将描述我的解决方案。 我们将使用部署dacpacs的sqlpackage工具。该工具支持许多参数。其中之一是GenerateSmartDefaults。请参阅here

我认为预部署脚本不必包含架构修改。只有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

答案 1 :(得分:1)

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

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

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

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