如何制作';模式比较';数据库管理->;SQL项目尊重SQL-CMD变量

如何制作';模式比较';数据库管理->;SQL项目尊重SQL-CMD变量,sql,visual-studio-2013,schema,database-project,schema-compare,Sql,Visual Studio 2013,Schema,Database Project,Schema Compare,我有一个VisualStudio2013解决方案,包含2个SQL项目DB1和DB2 DB1有一个引用DB2的存储过程 如果我在过程中使用.dacpac和同义词 SELECT * FROM [$(DB2)].[dbo].[Table1] 然后,将数据库中的模式与SQL项目进行比较错误地将上述内容检测为更改,因为它不处理变量/同义词 如果我用 SELECT * FROM DB2.[dbo].[Table1] 并将存储过程生成类型更改为None(以便项目生成),然后模式比较从数据库转到项目时**将

我有一个VisualStudio2013解决方案,包含2个SQL项目DB1和DB2

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

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

SELECT * FROM [$(DB2)].[dbo].[Table1]
然后,将数据库中的模式与SQL项目进行比较错误地将上述内容检测为更改,因为它不处理变量/同义词

如果我用

SELECT * FROM DB2.[dbo].[Table1]
并将存储过程生成类型更改为None(以便项目生成),然后模式比较从数据库转到项目时**将“看不到”项目中的存储过程,并在每次比较时向SQL数据库项目添加新的过程

在模式比较之后,我现在将看到

  • DB1
    • dbo
      • 存储过程
        • sp_myStoredProcedure.sql
        • sp_myStoredProcedure1.sql
        • sp_myStoredProceduren.sql
其中n=#的模式比较

如果有一种方法可以忽略生成错误SQL7501,那么它应该可以使用第二个选项工作,但它似乎不能被忽略

另一种解决方案是保存模式比较,并在所有引用DB2的过程中手动选择skip,不过我希望检测这些过程中的更改

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

更新 在测试了Kevin的答案后,我确定了为什么我的一些观点没有正确处理SC。他的答案在技术上是正确的,但是:

如果在DB1中有一个视图:

SELECT * FROM DB1.dbo.Table1 T1
INNER JOIN DB2.dbo.Table2 T2 
ON T2.Field1 = T1.Field1
在您的DB1SQL项目中,是原始的(没有自引用DB1)

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

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

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

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

我认为这个问题可以扩展到以下方面:

任何时候数据库SQL不构建SQL CMD变量都不会 已解析,并将导致可能模糊原始生成的错误 失败

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

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

最后,为了避免循环依赖(项目不能相互引用),我使用项目引用构建了引用DB2的DB1,但检查了“superss build errors In the referenced Project”。DB2没有构建,因为它引用了DB1

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

整个过程非常复杂,SQL项目应该允许相互引用(使用远程错误抑制),但不管怎样,最终我还是设法得到了2个db,它们将相互引用,并且所有这些都与同义词和模式比较兼容

只花了两天的时间


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

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

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

    调试

  • 致:

    调试
    释放
    
    正如您所看到的,这意味着在调试配置中,它将有一个不同的值来释放。在现实世界中,您可能会为目标服务器创建一个配置

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

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

    • 创建“DB1_核心”和“DB2_核心”项目。将其他数据库引用的对象放在核心项目中
    • 在DB1项目中,添加“DB1_Core”作为“相同的数据库”引用。这将确保在使用“Include Composite Objects=true”发布时,DB1项目会像以前一样发布—所有核心对象都将被包括在内
    • 对DB2项目执行同样的操作
    • DB1应该只需要对DB2_核心的引用,DB2引用DB1_核心。这打破了循环依赖关系,允许您安全地构建

    这是一种最佳实践,遵循与C#和其他项目类型类似的模式。有一个关于复合项目的演示-链接在.

    Kevin上,因为我怀疑这不起作用。也许
    SELECT * FROM dbo.Table1 T1
    INNER JOIN [$(DB2)].dbo.Table2 T2 
    ON T2.Field1 = T1.Field1
    
    <SqlCmdVar__1 Condition=" '$(Configuration)' == 'Debug' ">Debug</SqlCmdVar__1>
    <SqlCmdVar__1 Condition=" '$(Configuration)' == 'Release' ">Release</SqlCmdVar__1>