Почему эта зависимость NuGet отсутствует при компиляции проекта .NET Framework в зависимости от .NET Standard?

У меня есть решение Visual Studio с 3 проектами.

Верхний уровень - это консольное приложение .NET Framework 4.6.1 (проект A). Это зависит от библиотеки классов .NET Framework 4.6.1 (проект B). Проект B зависит от библиотеки классов .NET Standard 2.0 (проект C).

У меня есть код в Project C, который использует System.Data.SqlClient (пакет NuGet версии 4.6.1).

Из-за следующей известной проблемы https://github.com/dotnet/sdk/issues/901 Я также добавил System.Data.SqlClient в качестве зависимости NuGet в Project B (библиотека классов .NET Framework).

Это сценарий 1, и когда решение построено, System.Data.SqlClient копируется в папку / bin / Debug проекта A, и приложение запускается успешно.

Код для сценария 1 находится здесь https://github.com/JamesDunlop/TestDependencyFlowsNetStandard

Однако для сценария 2 я теперь ДОБАВЛЯЮ ссылку на проект в Project A, так что теперь он также напрямую ссылается / зависит от Project C (т.е. библиотеки стандартных классов .NET), а также Project B. Это имитирует то, что мне нужно. сделать в устаревшем приложении.

Очистите, восстановите и запустите. System.Data.SqlClient теперь отсутствует в папке / bin / Debug проекта A, и во время выполнения возникает исключение "System.IO.FileNotFoundException: 'Не удалось загрузить файл или сборку' System.Data.SqlClient"

Почему System.Data.SqlClient не копируется в / bin / Debug?

Обратите внимание, что я решил НЕ переносить проекты .NET Framework в PackageReferences, чтобы решить проблему https://github.com/dotnet/sdk/issues/901, поскольку мне нужно реализовать это в большом устаревшем решении ASP.NET, где это невозможно.

Я ожидал, что добавление ссылки на Project C будет иметь небольшой эффект, кроме (как было замечено), что это приведет к тому, что в папку / bin / Debug будет скопировано гораздо больше библиотек DLL с пересылкой типов. Но я бы не ожидал, что теперь будет отсутствовать System.Data.SqlClient.


person JamesDunlop    schedule 21.06.2019    source источник
comment
2 Перечисленные здесь версии представляют правила, которые NuGet использует для определения применимости данной стандартной библиотеки .NET. Хотя NuGet считает, что .NET Framework 4.6.1 поддерживает .NET Standard 1.5–2.0, существует несколько проблем с использованием библиотек .NET Standard, которые были созданы для этих версий из проектов .NET Framework 4.6.1. Для проектов .NET Framework, которым необходимо использовать такие библиотеки, мы рекомендуем обновить проект до целевой .NET Framework 4.7.2 или более поздней версии. (docs.microsoft.com/en-us/dotnet/standard/net -стандарт). Может быть, за веревку натянуть   -  person Sinaesthetic    schedule 24.06.2019
comment
Спасибо за предложение @Sinaesthetic. Я попытался обновить проекты .NET Framework до версии 4.7.2, но, к сожалению, проблема, о которой говорилось выше, все еще сохраняется.   -  person JamesDunlop    schedule 25.06.2019
comment
Добавление пакета System.Data.SqlClient NuGet также в проект A должно решить эту проблему. Для сценария 2 журнал MSBuild показывает, что он пытается разрешить эту зависимость от проекта C, который там отсутствует, потому что проект .NET Standard не копирует свои зависимости в папку bin. Для сценария 1 MSBuild разрешает его из проекта B, который завершается успешно.   -  person pfx    schedule 25.06.2019


Ответы (2)


Я повторю здесь свой комментарий выше, так как он считается правильным ответом.

Журнал MSBuild с уровнем подробности вывода сборки, установленным на уровне detailed, дает больше информации о том, что происходит.

Сценарий 1 (A относится к B, B относится к C)

Журнал сборки показывает, что проект A успешно разрешил свою System.Data.SqlClient зависимость от \bin\debug папки проекта B и скопировал ее локально.
(Поскольку проект B является библиотекой классов .NET Framework, его зависимости 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 пытается разрешить свою System.Data.SqlClient зависимость от NET Standard проекта C (и некоторых хорошо известных папок), но уже не от проекта B.
(Поскольку проект C является проектом NET Standard, это не так ' t скопируйте его NuGetdependencies в свою 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.

person pfx    schedule 26.06.2019

Комментарий 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 не пытается использовать каталог bin проекта B, и журнал сборки показывает это, как указано в 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> к <PropertyGroup> в .csproj для .NET Standard Project C, System.Data.SqlClient копируется в bin каталог этого .NET Standard проекта, и MSBuild затем может найти и скопировать его. в конечную папку вывода сборки.

ИЗМЕНИТЬ - приведенное выше предложение не работает, поскольку при запуске реального приложения DLL, которая помещается в выходной каталог, предназначена для неправильной платформы и несовместима с .NET Framework.

В качестве дополнительной информации, журналы сборки, на которые ссылается pfx, можно получить в среде Visual Studio IDE в соответствии с этим сообщение

Предложение pfx о добавлении System.Data.SqlClient в проект A работает, но этого я хотел избежать, потому что в реальном монолитном устаревшем приложении есть много эквивалентов Project A, где его нужно было бы добавить (а не просто добавить на следующий уровень выше Project B).

person JamesDunlop    schedule 26.06.2019