如何防止 SqlPackage.exe 在部署 dacpac 时删除和重新创建约束?
How can I prevent SqlPackage.exe from dropping and re-creating constraints when deploying a dacpac?
我有一个 Visual Studio sql 项目,其 table 定义如下:
CREATE TABLE [dbo].[Hoerses]
(
[HoersId] INT NOT NULL PRIMARY KEY,
[DatePurchased] datetime NOT NULL CONSTRAINT [DF_Hoerses_DatePurchased] DEFAULT DATETIMEFROMPARTS(1985,01,01,0,0,0,0)
)
当我使用 "Script" 命令瞄准一个预先存在的 SQL 数据库时
sqlpackage.exe /Action:Script /SourceFile:DatabaseProject1.dacpac /Profile:publish.xml /OutputPath:deployscript_test.sql /TargetPassword:redacted
然后我得到以下生成的 SQL,即使约束在前后具有相同的名称和定义:
PRINT N'Dropping [dbo].[DF_Hoerses_DatePurchased]...';
GO
ALTER TABLE [dbo].[Hoerses] DROP CONSTRAINT [DF_Hoerses_DatePurchased];
GO
PRINT N'Creating [dbo].[DF_Hoerses_DatePurchased]...';
GO
ALTER TABLE [dbo].[Hoerses]
ADD CONSTRAINT [DF_Hoerses_DatePurchased] DEFAULT DATETIMEFROMPARTS(1985,01,01,0,0,0,0) FOR [DatePurchased];
GO
PRINT N'Update complete.';
GO
(我主要担心试图阻止这种多余的重新创建是因为我偶尔会在实际 deployments/publishing 期间尝试删除约束时看到 "Lock request time out period exceeded." 错误)
问题显然出在 DATETIMEFROMPARTS
的使用上。
如果我改为将 table 声明为
CREATE TABLE [dbo].[Hoerses]
(
[HoersId] INT NOT NULL PRIMARY KEY,
[DatePurchased] datetime NOT NULL CONSTRAINT [DF_Hoerses_DatePurchased] DEFAULT '1985-01-01'
)
然后 SqlPackage.exe 不再尝试删除和重新添加约束。
Dacpac 部署的工作原理是将数据库架构的 XML 结构与您的 VS 项目中的结构进行比较。
有时,此过程会因句法细节而混淆,从而导致如您所描述的那样重复更改。
我的建议是您转到已部署的数据库,编写出有问题的对象的脚本,然后将其粘贴回该对象的 Visual Studio 文件的实现中。这解决了明显的差异,因此部署不再被误认为它需要实施更改。
我还找到了一篇对我有帮助的文章。
http://johnnydba.blogspot.com/2015/07/are-your-vs-database-projects-dropping.html
文章中提到的可能存在的问题基本上就是这些:
- 某些系统函数在 SQL 服务器中以小写形式表示,例如
getdate()
、sysutcdatetime()
、getutcdate()
和 newid()
。
myDate datetime2 DF_myTable_myDate DEFAULT(getdate()) NOT NULL
- 默认约束中的标量数值需要用双括号括起来
((0))
,但我注意到字符串值不需要。
myBit bit DF_myTable_myBit DEFAULT((0)) NOT NULL
- 过滤索引和检查约束条件必须用括号括起来
()
,列名必须在方括号中,比较运算符左右不能有空格
-- Column check
CONSTRAINT CH_myTable_someCheck CHECK ([myColumn]>(0))
-- Function check
CONSTRAINT CH_myTable_anotherCheck CHECK ([dbo].[someFunc]([myColumn],[myAnotherColumn])=(1))
- 有些列必须用方括号括起来
[]
这是用于约束的关键字大小写。
在您的默认设置中,对 getdate()
或 newid()
等关键字使用小写字母。
将始终删除这些约束:
CREATE TABLE [dbo].[APPLICATION_ERROR]
(
[ERROR_ID] UNIQUEIDENTIFIER
CONSTRAINT [CT_ERROR_ID] DEFAULT (NEWID()) NOT NULL,
[ERROR_DATE] DATETIME
CONSTRAINT [CT_ERROR_DATE] DEFAULT (GETDATE()) NULL
);
这些不会:
CREATE TABLE [dbo].[APPLICATION_ERROR]
(
[ERROR_ID] UNIQUEIDENTIFIER
CONSTRAINT [CT_ERROR_ID] DEFAULT (newid()) NOT NULL,
[ERROR_DATE] DATETIME
CONSTRAINT [CT_ERROR_DATE] DEFAULT (getdate()) NULL
);
如果约束是数字,你应该使用双括号:
[LABOR_AMOUNT] MONEY
CONSTRAINT [DF_LABOR_AMOUNT]
DEFAULT ((0)) NULL
您还应该将此添加到您的发布配置文件中,但这不是问题的核心:
<IgnoreKeywordCasing>True</IgnoreKeywordCasing>
我有一个 Visual Studio sql 项目,其 table 定义如下:
CREATE TABLE [dbo].[Hoerses]
(
[HoersId] INT NOT NULL PRIMARY KEY,
[DatePurchased] datetime NOT NULL CONSTRAINT [DF_Hoerses_DatePurchased] DEFAULT DATETIMEFROMPARTS(1985,01,01,0,0,0,0)
)
当我使用 "Script" 命令瞄准一个预先存在的 SQL 数据库时
sqlpackage.exe /Action:Script /SourceFile:DatabaseProject1.dacpac /Profile:publish.xml /OutputPath:deployscript_test.sql /TargetPassword:redacted
然后我得到以下生成的 SQL,即使约束在前后具有相同的名称和定义:
PRINT N'Dropping [dbo].[DF_Hoerses_DatePurchased]...';
GO
ALTER TABLE [dbo].[Hoerses] DROP CONSTRAINT [DF_Hoerses_DatePurchased];
GO
PRINT N'Creating [dbo].[DF_Hoerses_DatePurchased]...';
GO
ALTER TABLE [dbo].[Hoerses]
ADD CONSTRAINT [DF_Hoerses_DatePurchased] DEFAULT DATETIMEFROMPARTS(1985,01,01,0,0,0,0) FOR [DatePurchased];
GO
PRINT N'Update complete.';
GO
(我主要担心试图阻止这种多余的重新创建是因为我偶尔会在实际 deployments/publishing 期间尝试删除约束时看到 "Lock request time out period exceeded." 错误)
问题显然出在 DATETIMEFROMPARTS
的使用上。
如果我改为将 table 声明为
CREATE TABLE [dbo].[Hoerses]
(
[HoersId] INT NOT NULL PRIMARY KEY,
[DatePurchased] datetime NOT NULL CONSTRAINT [DF_Hoerses_DatePurchased] DEFAULT '1985-01-01'
)
然后 SqlPackage.exe 不再尝试删除和重新添加约束。
Dacpac 部署的工作原理是将数据库架构的 XML 结构与您的 VS 项目中的结构进行比较。 有时,此过程会因句法细节而混淆,从而导致如您所描述的那样重复更改。 我的建议是您转到已部署的数据库,编写出有问题的对象的脚本,然后将其粘贴回该对象的 Visual Studio 文件的实现中。这解决了明显的差异,因此部署不再被误认为它需要实施更改。
我还找到了一篇对我有帮助的文章。 http://johnnydba.blogspot.com/2015/07/are-your-vs-database-projects-dropping.html
文章中提到的可能存在的问题基本上就是这些:
- 某些系统函数在 SQL 服务器中以小写形式表示,例如
getdate()
、sysutcdatetime()
、getutcdate()
和newid()
。
myDate datetime2 DF_myTable_myDate DEFAULT(getdate()) NOT NULL
- 默认约束中的标量数值需要用双括号括起来
((0))
,但我注意到字符串值不需要。
myBit bit DF_myTable_myBit DEFAULT((0)) NOT NULL
- 过滤索引和检查约束条件必须用括号括起来
()
,列名必须在方括号中,比较运算符左右不能有空格
-- Column check
CONSTRAINT CH_myTable_someCheck CHECK ([myColumn]>(0))
-- Function check
CONSTRAINT CH_myTable_anotherCheck CHECK ([dbo].[someFunc]([myColumn],[myAnotherColumn])=(1))
- 有些列必须用方括号括起来
[]
这是用于约束的关键字大小写。
在您的默认设置中,对 getdate()
或 newid()
等关键字使用小写字母。
将始终删除这些约束:
CREATE TABLE [dbo].[APPLICATION_ERROR]
(
[ERROR_ID] UNIQUEIDENTIFIER
CONSTRAINT [CT_ERROR_ID] DEFAULT (NEWID()) NOT NULL,
[ERROR_DATE] DATETIME
CONSTRAINT [CT_ERROR_DATE] DEFAULT (GETDATE()) NULL
);
这些不会:
CREATE TABLE [dbo].[APPLICATION_ERROR]
(
[ERROR_ID] UNIQUEIDENTIFIER
CONSTRAINT [CT_ERROR_ID] DEFAULT (newid()) NOT NULL,
[ERROR_DATE] DATETIME
CONSTRAINT [CT_ERROR_DATE] DEFAULT (getdate()) NULL
);
如果约束是数字,你应该使用双括号:
[LABOR_AMOUNT] MONEY
CONSTRAINT [DF_LABOR_AMOUNT]
DEFAULT ((0)) NULL
您还应该将此添加到您的发布配置文件中,但这不是问题的核心:
<IgnoreKeywordCasing>True</IgnoreKeywordCasing>