Visual Studio 数据库项目 - 在部署前更改 table 不起作用
Visual Studio database project - altering table in pre-deployment doesn't work
我需要为 Visual Studio 2017 年的数据库项目更改 table 的复合主键,即在删除所有重复项后将其更改为 2 列而不是 4 列。我已经将删除重复的脚本放入预部署中,它是这样的:
CREATE TABLE tmp_table
(
<same columns as old_table>,
CONSTRAINT [PK_NewPK]
PRIMARY KEY CLUSTERED ([Column1], [Column2] ASC)
) ON [PRIMARY]
INSERT INTO tmp_table
(SELECT <unique data from old_table>)
TRUNCATE old_table
DROP old_table
EXEC sp_rename 'tmp_table', 'old_table'
它像魅力一样工作,但新的 old_table 在部署后仍然具有旧的 4 列主键,这并不奇怪,因为 old_table 的代码没有被更改。问题是,当我尝试编辑 old_table 以拥有 2 列 PK 时,部署失败并显示
SQL72014: .Net SqlClient Data Provider:
Msg 3728, Level 16, State 1, Line 1
'DF__old_table__' is not a constraint.
我假设对 table 的代码更改是在预部署脚本之后应用的,但是这里的事件顺序看起来非常错误,我看不出如何修复它。
好吧,在重新阅读 this post 几遍后,我意识到这里的事件顺序有什么问题(是的,pre-pre-deployment 阶段问题) - 也就是说,部署代码是根据模型比较结果生成的,模型比较是在执行预部署代码之前完成的。所以,它是这样的:
- 比较源和目标数据库模型,记录 old_table 的主键更改,并修改部署脚本以反映这一点,包括删除默认约束;
- 预部署代码已执行,old_table 发生了很大变化,但部署脚本不知道;
- 部署代码已执行,并在尝试删除该默认约束时立即崩溃,因为它不再存在(但我们检查时它在那里,只是它不存在,甚至不应该......呃);
- 利润(不是真的)。
是的,它应该是这样工作的,我确实遗漏了一些明显的东西。现在我知道了。
我的解决方案是在预部署脚本的末尾创建 DF__old_table__ 约束,因此当部署代码寻找它时它仍然存在于更改后的 old_table 中,但随后它将消失,因为 old_table 的部署代码没有任何默认值,即使有,约束也会有不同的名称(因为未命名的约束是邪恶的)。
说到这里,此解决方案并非 100% 可靠,因为未命名的约束不能保证在您的开发机器和生产服务器上具有相同的随机生成名称。而且它很hacky。但它适用于我们的设置,而且我能想出的任何替代方案甚至更骇人听闻。
我需要为 Visual Studio 2017 年的数据库项目更改 table 的复合主键,即在删除所有重复项后将其更改为 2 列而不是 4 列。我已经将删除重复的脚本放入预部署中,它是这样的:
CREATE TABLE tmp_table
(
<same columns as old_table>,
CONSTRAINT [PK_NewPK]
PRIMARY KEY CLUSTERED ([Column1], [Column2] ASC)
) ON [PRIMARY]
INSERT INTO tmp_table
(SELECT <unique data from old_table>)
TRUNCATE old_table
DROP old_table
EXEC sp_rename 'tmp_table', 'old_table'
它像魅力一样工作,但新的 old_table 在部署后仍然具有旧的 4 列主键,这并不奇怪,因为 old_table 的代码没有被更改。问题是,当我尝试编辑 old_table 以拥有 2 列 PK 时,部署失败并显示
SQL72014: .Net SqlClient Data Provider:
Msg 3728, Level 16, State 1, Line 1
'DF__old_table__' is not a constraint.
我假设对 table 的代码更改是在预部署脚本之后应用的,但是这里的事件顺序看起来非常错误,我看不出如何修复它。
好吧,在重新阅读 this post 几遍后,我意识到这里的事件顺序有什么问题(是的,pre-pre-deployment 阶段问题) - 也就是说,部署代码是根据模型比较结果生成的,模型比较是在执行预部署代码之前完成的。所以,它是这样的:
- 比较源和目标数据库模型,记录 old_table 的主键更改,并修改部署脚本以反映这一点,包括删除默认约束;
- 预部署代码已执行,old_table 发生了很大变化,但部署脚本不知道;
- 部署代码已执行,并在尝试删除该默认约束时立即崩溃,因为它不再存在(但我们检查时它在那里,只是它不存在,甚至不应该......呃);
- 利润(不是真的)。
是的,它应该是这样工作的,我确实遗漏了一些明显的东西。现在我知道了。
我的解决方案是在预部署脚本的末尾创建 DF__old_table__ 约束,因此当部署代码寻找它时它仍然存在于更改后的 old_table 中,但随后它将消失,因为 old_table 的部署代码没有任何默认值,即使有,约束也会有不同的名称(因为未命名的约束是邪恶的)。
说到这里,此解决方案并非 100% 可靠,因为未命名的约束不能保证在您的开发机器和生产服务器上具有相同的随机生成名称。而且它很hacky。但它适用于我们的设置,而且我能想出的任何替代方案甚至更骇人听闻。