【问题标题】:How to make 'Schema Compare' of Database->SQL Project respect SQL-CMD Variables如何使数据库-> SQL 项目的“架构比较”尊重 SQL-CMD 变量
【发布时间】:2015-07-10 06:25:41
【问题描述】:

我有一个带有 2 个 SQL 项目 DB1、DB2 的 Visual Studio 2013 解决方案。

DB1 有一个引用 DB2 的存储过程。

如果我在程序中使用 .dacpac 和同义词

SELECT * FROM [$(DB2)].[dbo].[Table1]

然后Compare Schema from Database to the SQL Project错误地将上述内容检测为更改,因为它不处理变量/同义词。

如果我改为使用

SELECT * FROM DB2.[dbo].[Table1]

并将存储过程构建类型更改为 None(以便项目构建)然后架构比较 当从数据库 到 Proejct** 将“看不到”将 proc 存储在我的项目中,并在每次比较时向 SQL 数据库项目添加一个新的 proc

架构比较后,我现在会看到

  • DB1
    • dbo
      • 存储过程
        • sp_myStoredProcedure.sql
        • sp_myStoredProcedure1.sql
        • sp_myStoredProceduren.sql

其中 n = 比较模式的数量!

如果有办法忽略 Build Error SQL7501,那么它应该可以使用第二个选项,但它似乎不能被忽略。

另一个解决方案是保存模式比较并在所有引用 DB2 的过程上手动选择跳过,但是我想检测这些过程中的变化。

这似乎是一个简单而常见的用例。有人想出解决这个设计缺陷的方法吗?

更新

在测试了凯文的回答后,我已经确定了为什么我的某些观点没有被 SC 正确处理。然而,他的回答在技术上是正确的:

如果您在 DB1 中有视图:

SELECT * FROM DB1.dbo.Table1 T1
INNER JOIN DB2.dbo.Table2 T2 
ON T2.Field1 = T1.Field1

并且在您的 DB1 SQL 项目中是原始的(没有自引用 DB1)

SELECT * FROM dbo.Table1 T1
INNER JOIN [$(DB2)].dbo.Table2 T2 
ON T2.Field1 = T1.Field1

架构比较将无法正确替换变量并识别更改:[$(DB2)] -> $(DB2)

问题是自引用 DB1.dbo.Table 在我的例子中,它被插入到大量连接的中途,其中许多连接是 DB2 引用。

这会导致 SC 错误地将所有 [$(DB2)] 标记为更改。可能是因为数据库 sql 没有在 VS 中“构建”并恢复为文本比较。

所以这并不是一个真正的错误,但对于不手动比较 SQL 的每一行的开发人员来说,这是一个令人困惑的结果。

我认为这个问题可以扩展为:

任何时候数据库 SQL 不构建 SQL CMD 变量都不会 解析并会导致可能掩盖原始构建的错误 失败。

我还必须补充一点,在我的例子中,DB2 也引用了 DB1!

这可能是未能正确报告错误的部分原因。

最后,为了避免循环依赖(项目不能相互引用),我使用项目引用构建了引用 DB2 的 DB1,但检查了“抑制引用项目中的构建错误”。 DB2 没有构建,因为它引用了 DB1。

DB1 构建后,我使用 bin 文件夹中的输出 DACPAC,将其复制到另一个位置,并在 DB2 中引用该 DB1 DACPAC。现在,每当 DB1 发生更改时,我都必须重建 DACPAC 复制到此文件夹。幸运的是,这不会改变太多。

整个过程非常复杂,SQL 项目应该允许相互引用(通过远程错误抑制),但不管最终我设法获得了 2 个要构建的相互引用的 db,并且所有同义词和架构比较兼容!

而且只用了2天的奋斗时间!

https://connect.microsoft.com/VisualStudio/feedback/details/1291555

【问题讨论】:

    标签: sql visual-studio-2013 schema database-project schema-compare


    【解决方案1】:

    可以通过更改数据库项目属性中的 SQLCMD 变量默认值或本地设置来避免此问题。行为是: - 如果定义了本地值,这就是模式比较中使用的值 - 如果未定义本地值,则将使用默认值。 因此,更新 Local 值以匹配您引用的数据库名称,重建并进行新的架构比较应该可以为您解决这个问题。

    如果您有多个要定位的数据库,现在最好的选择是根据您的配置为“本地”值设置不同的值。这意味着:

    1. 在 Build -> Configuration Manager 对话框中为每个目标创建一个新的解决方案配置。这使您可以更改一些设置并让它们因配置而异
    2. 您编辑应该位于解决方案基础中的 projectname.sqlproj.user 文件。这包含数据库的本地值,您可以根据配置更改值。在我的示例中,我只有 1 个变量 $(DB2),它映射到用户设置中的 SqlCmdVar__1 设置。我将其更改为:

      调试

    收件人:

    <SqlCmdVar__1 Condition=" '$(Configuration)' == 'Debug' ">Debug</SqlCmdVar__1>
    <SqlCmdVar__1 Condition=" '$(Configuration)' == 'Release' ">Release</SqlCmdVar__1>
    

    如您所见,这意味着在 Debug 配置中,它会具有不同的释放值。在现实世界中,您可能会为每个目标服务器创建一个配置

    这比理想情况下更麻烦,但它确实解决了您的问题,并且在现有工具的情况下是最好的方法。

    更新:要解决数据库项目之间循环依赖的潜在问题,您应该使用复合项目。基本流程是:

    • 创建“DB1_Core”和“DB2_Core”项目。把其他数据库引用的对象放到Core项目中
    • 在您的 DB1 项目中添加“DB1_Core”作为“相同数据库”引用。这将确保在使用“Include Composite Objects = true”发布时,您的 DB1 项目会像以前一样发布 - 所有核心对象都将被包含在内。
    • 对 DB2 项目做同样的事情
    • DB1 应该只需要引用 DB2_Core,而 DB2 引用 DB1_Core。这打破了循环依赖,让您可以安全地构建。

    这是一种最佳实践,并遵循与 C# 和其他项目类型类似的模式。有一个涵盖复合项目的演示文稿 - 链接在 SSDT blog here。

    【讨论】:

    • 凯文我怀疑这不起作用。也许您误读了我的问题并认为我想从项目中更新数据库?模式比较(数据库 -> 项目)用 DB2 覆盖 [$(DB2)],然后视图/proc 无法构建。 MS 需要修复这个错误,因为它使整个事情对于想要在 Management Studio 中对开发数据库进行更改然后使用模式比较更新项目的大量开发团队来说完全无用。
    • 实际上我验证了自己这不会发生从数据库 -> 项目按照上述步骤,至少使用标准步骤(并且不将构建类型更改为无,这将存储过程从项目中排除建造)。请重新激活 Connect 问题并包含其他步骤来说明它在您的案例中失败的原因,我会对其进行调查,但这里的基本案例确实有效
    • 谢谢凯文,我按照你的步骤写信了。我今天早上重新测试,我注意到一些视图被正确处理,但不是全部!似乎没有一个直截了当的解释,例如我在 DB1 中有 2 个视图具有与 DB2 相同的内部连接,第一个 proc 正确地没有显示为 SC 中的更改,而第二个使用相同的变量 [$( DB2)] 检测为与 DB2 的差异。两者都将建立。我会进一步调查。
    • Kevin 我已经确定了它为什么不起作用并更新了我上面的答案。感谢您的帮助,如果您可以以任何方式编辑您的回复(stackoverflow 规则),我会将您的回复标记为答案。
    • 嗨,汤姆,很高兴您找到了解决方法。我已经更新了关于使用复合项目解决循环依赖问题的 cmets。最后,您是对的,当我们更新目标时,我们确实会丢失 SQLCMD 变量 - 这是产品的已知限制。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 2019-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    相关资源
    最近更新 更多