SSDT 数据库解决方案中的重复项目引用

Posted

技术标签:

【中文标题】SSDT 数据库解决方案中的重复项目引用【英文标题】:Duplicate project reference in SSDT Database solution 【发布时间】:2019-04-05 12:32:33 【问题描述】:

我在一个包含多个 SQL Server 数据库项目的解决方案中使用 tSQLt。对于每个项目,都有一个引用原始项目和 tSQLt 源的 .Test 项目。

以下是解决方案的简要概述:

解决方案

项目DB1 项目DB1.Test 项目DB2 项目DB2.Test 项目TSQLT

在哪里

项目DB2 依赖于项目DB1 项目DB1.Test 依赖于DB1TSQLT(使用“相同数据库”选项) 项目DB2.Test 依赖于DB2TSQLT(使用“相同数据库”选项)和DB1.Test(相同的服务器,不同的数据库和一个变量)。因为DB1.Test 依赖于DB1TSQLT,所以这个项目也依赖于它们(使用与DB1.Test 相同的变量)。

问题是当从DB2.Test 引用时,对DB1.Test 的引用并没有带来TSQLTDB1 对象,所以我得到了大量关于未解析引用的警告列表。 与DB1 相关的警告可以通过使用与DB1.Test 相同的变量引用该项目来解决,但TSQLT 已在此处引用,当我尝试引用它两次时,它会导致“重复引用”错误。

一个明显的解决方案是在解决方案中制作 TSQLT 项目的副本,但老实说,我只是不想重复代码。

另一种方法是使用不同的配置构建该项目,并简单地引用 .dacpac 文件,但这感觉像是一种 hack。

理论上,我们可以将 TSQLT 项目移出解决方案,并拥有 dacpac 文件的多个副本并引用这些副本,但是我试图将所有内容保存在一个地方。

目前我们没有 NuGet 存储库,因此使用 NuGet 包分发代码以使该部分保持最新也不起作用。

我尝试了两次引用它,但是使用不同的变量名,仍然会导致重复引用错误。

我知道,嵌套引用场景中未解决的引用错误可以通过将所有级别添加到项目中作为参考来解决,但在这种情况下,其中一个项目被使用两次并且不允许重复。

当存在嵌套引用时,是否有任何解决方案可以继续引用?

或者在构建期间将生成的 dacpac 文件从一个项目复制到另一个项目时使用自定义(唯一)名称保存本地副本?

请注意,没有循环引用,只是一个项目在解决方案的多个级别中使用,并且没有为所有实例设置 TSQLT 引用,构建工作正常,只是警告很烦人。

我知道“抑制警告”选项,但我希望将其关闭。 (这不会使对象神奇地出现在 IntelliSense 中)。

在这种情况下,打开或关闭“本地复制”选项不会对行为产生任何影响。

【问题讨论】:

【参考方案1】:

我找到了一个解决方案,它仍然有点像 hack,但工作正常。

构建事件

在公共项目中添加构建后事件:

    右键单击通用项目(本例中为 TSQLT) 选择Properties... 转到Build Events 标签 点击Edit Post-build... 将以下代码复制到编辑器窗口中 根据您的需要进行修改

    完成后全部保存(这将保存项目和解决方案文件)

    复制 "$(ProjectName).dacpac" "$(ProjectName)_DB1.dacpac" /Y 复制 "$(ProjectName).dacpac" "$(ProjectName)_DB2.dacpac" /Y

这将在输出文件夹中创建 TSQLT.dacpac 文件的副本(将创建TSQLT_DB1.dacpacTSQLT_DB2.dacpac 文件)。

确保 dacpac 文件的构建路径使用 $(ProjectName) 变量,或使用硬编码名称并相应地修改构建事件。

数据库参考

将这些文件作为项目中的数据层应用程序引用。

如果您有多个构建配置,请打开 .sqlproj 文件并对其进行编辑以使构建路径动态:

<ArtifactReference Include="..\.build\$(Configuration)\TSQLT\TSQLT_DB1.dacpac">
  <HintPath>..\.build\$(Configuration)\TSQLT\TSQLT_DB1.dacpac</HintPath>
  <SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
  <DatabaseSqlCmdVariable>DB1</DatabaseSqlCmdVariable>
  <Private>False</Private>
</ArtifactReference>
<ArtifactReference Include="..\.build\$(Configuration)\TSQLT\TSQLT_DB2.dacpac">
  <HintPath>..\.build\$(Configuration)\TSQLT\TSQLT_DB2.dacpac</HintPath>
  <SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
  <DatabaseSqlCmdVariable>DB2</DatabaseSqlCmdVariable>
  <Private>False</Private>
</ArtifactReference>

注意路径中的$(Configuration)。此方法假定所有项目的构建配置名称都相同。 (基本上我们在这里想要和构建路径中相同的东西(

现在您可以删除原始项目引用。

构建依赖

通过删除项目引用,Visual Studio 也删除了构建依赖项。

    右键单击解决方案 选择properties... 转到Common Properties / Project Dependencies 从下拉列表中选择项目 勾选引用项目前面的复选框

这可确保构建当前项目将触发所引用项目的构建(并将运行构建后事件)。

备注

我确实更新了解决方案中所有使用 TSQLT 的项目以拥有工件引用而不是项目引用,这使解决方案更加一致。

我没有更改对其他项目的引用,因为我对它们没有这种问题。

【讨论】:

以上是关于SSDT 数据库解决方案中的重复项目引用的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 2012 SSDT 解决方案中引用 CLR 项目

SSDT 很长时间加载项目和未解决的参考

SSDT/VS2015 数据库部署——发布忽略嵌套视图

带有 dacpac 参考的 SSDT 未解析参考

引用 SSDT 项目的 WiX 项目无法在 TFSBuild 中构建 - 未定义的预处理器变量“$(var.DatabaseProject.TargetDir)”

修复或避免在 SSDT 引用 Azure 托管实例中的主数据库时出现 SQL71501 和 SQL71561 构建错误?