为什么在根据 .NET Standard 编译 .NET Framework 项目时缺少此 NuGet 依赖项?

Why is this NuGet dependency missing when compiling .NET Framework project depending on .NET Standard?

我有一个 Visual Studio 解决方案,有 3 个项目。

顶级是 .NET Framework 4.6.1 控制台应用程序(项目 A)。 它依赖于 .NET Framework 4.6.1 Class 库(项目 B)。 项目 B 依赖于 .NET Standard 2.0 Class 库(项目 C)。

我在项目 C 中有一些代码使用 System.Data.SqlClient(NuGet 包版本 4.6.1)。

由于以下已知问题https://github.com/dotnet/sdk/issues/901,我还添加了 System.Data.SqlClient 作为项目 B(.NET Framework Class 库)的 NuGet 依赖项。

这是场景 1,构建解决方案时,System.Data.SqlClient 被复制到项目 A 的 /bin/Debug 文件夹,应用程序 运行 成功。

场景1的代码在这里https://github.com/JamesDunlop/TestDependencyFlowsNetStandard

但是,对于场景 2,我现在添加了对项目 A 的项目引用,这样它现在也直接 references/depends-on 项目 C(即 .NET Standard Class 库),以及项目 B。这模拟了我需要在遗留应用程序中执行的操作。

清理并重建 运行。 System.Data.SqlClient 现在在项目 A 的 /bin/Debug 文件夹中丢失,并且在 运行 时出现异常 "System.IO.FileNotFoundException: 'Could not load file or assembly 'System.Data.SqlClient"

为什么 System.Data.SqlClient 没有被复制到 /bin/Debug?

请注意,我选择不将 .NET Framework 项目迁移到 PackageReferences 以解决问题 https://github.com/dotnet/sdk/issues/901,因为我需要在大型遗留 ASP.NET 解决方案中实现它不可行。

我希望添加对项目 C 的引用不会有什么影响,除了(如观察到的那样)它会导致更多类型转发 DLL 被复制到 /bin/Debug 文件夹。但我不希望 System.Data.SqlClient 现在不见了。

pfx 对原始问题的评论基本上回答了问题。

在场景 1 中,我们在构建日志中看到了这一点

3>  Dependency "System.Data.SqlClient, Version=4.5.0.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
3>      Resolved file path is "C:\dev\testing\TestDependencyFlowsNetStandard\TestDependencyFlows.Library\bin\Debug\System.Data.SqlClient.dll".

对于场景 2,MSBuild 不会尝试使用项目 B 的 bin 目录,构建日志显示了 pfx

3> For SearchPath "C:\dev\testing\TestDependencyFlowsNetStandard\TestDependencyFlows.Library.NetStandard\bin\Debug\netstandard2.0".
3>          Considered "C:\dev\testing\TestDependencyFlowsNetStandard\TestDependencyFlows.Library.NetStandard\bin\Debug\netstandard2.0\System.Data.SqlClient.winmd", but it didn't exist.
3>          Considered "C:\dev\testing\TestDependencyFlowsNetStandard\TestDependencyFlows.Library.NetStandard\bin\Debug\netstandard2.0\System.Data.SqlClient.dll", but it didn't exist.
3>          Considered "C:\dev\testing\TestDependencyFlowsNetStandard\TestDependencyFlows.Library.NetStandard\bin\Debug\netstandard2.0\System.Data.SqlClient.exe", but it didn't exist.

此见解提供了解决方案 2 的解决方案。

使用此 中的解决方案,通过将 <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> 添加到 .NET Standard 项目 C 的 .csproj 中的 <PropertyGroup>,System.Data.SqlClient 被复制到该 .NET Standard 项目的 bin 目录,然后 MSBuild 能够找到它并将其复制到最终生成输出文件夹。

编辑 - 上面的建议不起作用,因为当 运行 一个真正的应用程序被推送到输出目录的 DLL 是针对错误的平台并且与 .NET Framework 不兼容。

作为进一步的信息,pfx 引用的构建日志可以在 Visual Studio IDE 中按照此 post

pfxSystem.Data.SqlClient 添加到项目 A 的建议可行,但这是我想避免的事情,因为在真正的单一遗留应用程序中,有许多项目 A 的等价物需要被添加(而不是简单地将其添加到项目 B 的下一个级别)。

我会在这里重复我上面的评论,因为它被认为是有效的答案。

MSBuild 日志,其构建输出详细程度设置为 detailed 级别,可以更深入地了解发生的情况。

场景一(A引用B,B引用C)

构建日志显示项目 A 已成功从项目 B 的 \bin\debug 文件夹中解析其 System.Data.SqlClient 依赖项并将其复制到本地。
(由于项目 B 是一个 .NET Framework class 库,它的 NuGet 依赖项确实被复制到它的 bin 文件夹中。)

Dependency "System.Data.SqlClient, Version=4.5.0.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
  Resolved file path is "C:\...\TestDependencyFlows.Library\bin\Debug\System.Data.SqlClient.dll".

场景2(A引用B和C,B引用C)

构建日志提到项目 A 试图从 NET Standard 项目 C(和一些众所周知的文件夹)中解决其 System.Data.SqlClient 依赖关系,但不再从项目 B 中解决。
(因为项目 C 是一个 NET Standard 项目,它不会将其 NuGet 依赖项复制到其 bin 文件夹。)
所有这些尝试都失败了,并显示该文件在这些位置不存在的消息。

Dependency "System.Data.SqlClient, Version=4.5.0.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
  Could not resolve this reference. Could not locate the assembly "System.Data.SqlClient, Version=4.5.0.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". 
  Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors.
  For SearchPath "C:\...\TestDependencyFlows.Library.NetStandard\bin\Debug\netstandard2.0".
      Considered "C:\...\TestDependencyFlows.Library.NetStandard\bin\Debug\netstandard2.0\System.Data.SqlClient.winmd", but it didn't exist.
      Considered "C:\...\TTestDependencyFlows.Library.NetStandard\bin\Debug\netstandard2.0\System.Data.SqlClient.dll", but it didn't exist.
      Considered "C:\...\TestDependencyFlows.Library.NetStandard\bin\Debug\netstandard2.0\System.Data.SqlClient.exe", but it didn't exist.
      ...

一种解决方案是将 System.Data.SqlClient NuGet 包也添加到项目 A。