我一直在使用.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发布以满足此类更新的需要?
答案 0 :(得分:2)
我将描述我的解决方案。 我们将使用部署dacpacs的sqlpackage工具。该工具支持许多参数。其中之一是GenerateSmartDefaults。请参阅here。
我认为预部署脚本不必包含架构修改。只有SELECT,INSERT,UPDATE,DELETE语句。部署后脚本也是如此。
答案 1 :(得分:1)
我认为你试图以错误的顺序做这件事。默认情况下,SSDT将不会检查约束,直到整个更新完成后 - 即使在部署后脚本之后也是如此。这意味着您应该能够使用默认和约束在项目中添加表,在Post-Deploy脚本中发出数据插入/更新,并让SSDT在完成所有操作后启用FK约束。
如果您对此不满意,可以按以下顺序执行此操作:
在大多数情况下,如果您的选项设置正确以便在其他所有内容之后启用检查约束,我认为您不必完成第二个过程。