7

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

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

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

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

然后将数据库中的模式比较到 SQL 项目错误地将上述内容检测为更改,因为它不处理变量/同义词。

如果相反我使用

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

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

经过架构比较后,我现在将看到

  • DB1
    • 德博
      • 存储过程
        • sp_myStoredProcedure.sql
        • sp_myStoredProcedure1.sql
        • sp_myStoredProcedure n .sql

其中 n = # of schema 比较!

如果有办法忽略构建错误 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 个相互引用的数据库,并且所有同义词和模式比较兼容!

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

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

4

1 回答 1

6

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

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

  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 博客上

于 2015-04-30T20:23:51.230 回答