SSDT 数据库解决方案中的重复项目引用
Duplicate project reference in SSDT Database solution
我在一个包含多个 SQL 服务器数据库项目的解决方案中使用 tSQLt。对于每个项目,都有一个 .Test 项目引用原始项目和 tSQLt 源。
这里是解决方案的简要概述:
解决方案
- 项目
DB1
- 项目
DB1.Test
- 项目
DB2
- 项目
DB2.Test
- 项目
TSQLT
在哪里
- 项目
DB2
取决于项目 DB1
- 项目
DB1.Test
依赖于 DB1
和 TSQLT
(使用 'Same database' 选项)
- 项目
DB2.Test
依赖于 DB2
和 TSQLT
(使用 'Same database' 选项)和 DB1.Test
(同一服务器,不同的数据库有一个变量).因为 DB1.Test
依赖于 DB1
和 TSQLT
,这个项目也依赖于它们(使用与 DB1.Test
相同的变量)。
问题是当从 DB2.Test
引用时,对 DB1.Test
的引用不会带来 TSQLT
和 DB1
对象,所以我得到了一个巨大的列表关于未解决引用的警告。
与 DB1
相关的警告可以通过使用与 DB1.Test
相同的变量引用该项目来解决,但是 TSQLT
已在此处引用,当我尝试引用它两次时,它会导致 "duplicate reference"错误。
一个明显的解决方案是复制解决方案中的 TSQLT 项目,但老实说,我只是不想复制代码。
另一种方法是使用不同的配置来构建该项目,而只是引用 .dacpac
文件,但这感觉就像是 hack。
我们理论上可以将 TSQLT 项目移到解决方案之外,并拥有 dacpac
文件的多个副本并引用它们,但我试图将所有内容都放在一个地方。
目前我们没有适当的 NuGet 存储库,因此使用 NuGet 包分发代码以使该部分保持最新也不起作用。
我尝试引用了两次,但变量名不同,仍然导致重复引用错误。
我知道,嵌套引用场景中未解决的引用错误可以通过将所有级别添加到项目作为引用来解决,但在这种情况下,其中一个项目被使用了两次,并且不允许重复。
有嵌套引用时继续引用的解决方案吗?
或者在构建过程中从一个项目复制到另一个项目时使用自定义(唯一)名称保存构建过程中生成的 dacpac 文件的本地副本?
请注意,没有循环引用,只是一个项目在解决方案的多个级别中使用,并且没有为所有实例提供 TSQLT 引用,构建工作正常,只是警告很烦人。
我知道 'suppress warnings' 选项,但我想将其关闭。 (这不会使对象神奇地出现在 IntelliSense 中)。
在这种情况下,打开或关闭 'Local Copy' 选项不会对行为产生任何影响。
我找到了一个解决方案,它仍然有点像 hack,但工作正常。
构建事件
向公共项目添加一个post-构建事件:
- 右键单击公共项目(在本例中为 TSQLT)
- Select
Properties...
- 转到
Build Events
选项卡
- 点击
Edit Post-build...
- 将以下代码复制到编辑器中window
- 根据您的需要修改它
完成后全部保存(这将保存项目和解决方案文件)
复制 "$(ProjectName).dacpac" "$(ProjectName)_DB1.dacpac" /Y
复制 "$(ProjectName).dacpac" "$(ProjectName)_DB2.dacpac" /Y
这将在输出文件夹中创建 TSQLT.dacpac 文件的副本(将创建 TSQLT_DB1.dacpac
和 TSQLT_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 也删除了构建依赖项。
- 右键单击解决方案
- Select
properties...
- 转到
Common Properties
/ Project Dependencies
- Select 下拉列表中的项目
- 勾选引用项目前的复选框
这确保构建当前项目将触发引用项目的构建(这将 运行 post-build 事件)。
备注
我确实更新了解决方案中使用 TSQLT 的所有项目,以使用工件引用而不是项目引用,这使解决方案更加一致。
我没有更改对其他项目的引用,因为我没有遇到此类问题。
我在一个包含多个 SQL 服务器数据库项目的解决方案中使用 tSQLt。对于每个项目,都有一个 .Test 项目引用原始项目和 tSQLt 源。
这里是解决方案的简要概述:
解决方案
- 项目
DB1
- 项目
DB1.Test
- 项目
DB2
- 项目
DB2.Test
- 项目
TSQLT
在哪里
- 项目
DB2
取决于项目DB1
- 项目
DB1.Test
依赖于DB1
和TSQLT
(使用 'Same database' 选项) - 项目
DB2.Test
依赖于DB2
和TSQLT
(使用 'Same database' 选项)和DB1.Test
(同一服务器,不同的数据库有一个变量).因为DB1.Test
依赖于DB1
和TSQLT
,这个项目也依赖于它们(使用与DB1.Test
相同的变量)。
问题是当从 DB2.Test
引用时,对 DB1.Test
的引用不会带来 TSQLT
和 DB1
对象,所以我得到了一个巨大的列表关于未解决引用的警告。
与 DB1
相关的警告可以通过使用与 DB1.Test
相同的变量引用该项目来解决,但是 TSQLT
已在此处引用,当我尝试引用它两次时,它会导致 "duplicate reference"错误。
一个明显的解决方案是复制解决方案中的 TSQLT 项目,但老实说,我只是不想复制代码。
另一种方法是使用不同的配置来构建该项目,而只是引用 .dacpac
文件,但这感觉就像是 hack。
我们理论上可以将 TSQLT 项目移到解决方案之外,并拥有 dacpac
文件的多个副本并引用它们,但我试图将所有内容都放在一个地方。
目前我们没有适当的 NuGet 存储库,因此使用 NuGet 包分发代码以使该部分保持最新也不起作用。
我尝试引用了两次,但变量名不同,仍然导致重复引用错误。
我知道,嵌套引用场景中未解决的引用错误可以通过将所有级别添加到项目作为引用来解决,但在这种情况下,其中一个项目被使用了两次,并且不允许重复。
有嵌套引用时继续引用的解决方案吗?
或者在构建过程中从一个项目复制到另一个项目时使用自定义(唯一)名称保存构建过程中生成的 dacpac 文件的本地副本?
请注意,没有循环引用,只是一个项目在解决方案的多个级别中使用,并且没有为所有实例提供 TSQLT 引用,构建工作正常,只是警告很烦人。
我知道 'suppress warnings' 选项,但我想将其关闭。 (这不会使对象神奇地出现在 IntelliSense 中)。
在这种情况下,打开或关闭 'Local Copy' 选项不会对行为产生任何影响。
我找到了一个解决方案,它仍然有点像 hack,但工作正常。
构建事件
向公共项目添加一个post-构建事件:
- 右键单击公共项目(在本例中为 TSQLT)
- Select
Properties...
- 转到
Build Events
选项卡 - 点击
Edit Post-build...
- 将以下代码复制到编辑器中window
- 根据您的需要修改它
完成后全部保存(这将保存项目和解决方案文件)
复制 "$(ProjectName).dacpac" "$(ProjectName)_DB1.dacpac" /Y 复制 "$(ProjectName).dacpac" "$(ProjectName)_DB2.dacpac" /Y
这将在输出文件夹中创建 TSQLT.dacpac 文件的副本(将创建 TSQLT_DB1.dacpac
和 TSQLT_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 也删除了构建依赖项。
- 右键单击解决方案
- Select
properties...
- 转到
Common Properties
/Project Dependencies
- Select 下拉列表中的项目
- 勾选引用项目前的复选框
这确保构建当前项目将触发引用项目的构建(这将 运行 post-build 事件)。
备注
我确实更新了解决方案中使用 TSQLT 的所有项目,以使用工件引用而不是项目引用,这使解决方案更加一致。
我没有更改对其他项目的引用,因为我没有遇到此类问题。