Fixing Error NU1202: Package Microsoft.EntityFrameworkCore.Tools 6.0.1 is not compatible with netcoreapp2.2 (.NETCoreApp,Version=v2.2)

Migrating an AspNetCore web and database application from version 2.2 to current .Net 6, I came across an occasional build error:

error NU1202: Package Microsoft.EntityFrameworkCore.Tools 6.0.1 is not compatible with netcoreapp2.2 (.NETCoreApp,Version=v2.2). Package Microsoft.EntityFrameworkCore.Tools 6.0.1 supports: net6.0 (.NETCoreApp,Version=v6.0) 

The error went away by unchecking the Option “Allow NuGet to download missing packages” under “Nuget Package Manager”, so I did not bother any longer.

Unfortunately, the error returned as soon as I ran an Azure Build Task on the project. The task failed with a simple message

##[error]Packages failed to restore

without any indication what exactly failed, what was to be restored, and, especially, why.

Going through the log file, I found that nuget tried to restore packages for .Net 6 (good), but also für .NetCore 2.2 (bad):

2022-04-06T13:59:20.3799748Z          Restoring packages for .NETCoreApp,Version=v6.0...
2022-04-06T13:59:20.4022386Z          Resolving conflicts for .NETCoreApp,Version=v2.2...
2022-04-06T13:59:20.4605261Z          Resolving conflicts for net6.0-windows7.0...
2022-04-06T13:59:20.5840720Z          Checking compatibility of packages on .NETCoreApp,Version=v2.2.
2022-04-06T13:59:20.5886337Z          Checking compatibility for microsoft.entityframeworkcore.tools-netcoreapp2.2-[6.0.1, ) 1.0.0 with .NETCoreApp,Version=v2.2.
2022-04-06T13:59:20.6014642Z          Checking compatibility for Microsoft.EntityFrameworkCore.Tools 6.0.1 with .NETCoreApp,Version=v2.2.
2022-04-06T13:59:20.6016218Z      1>D:\DevOpsAgents\some\path\Project.Data.csproj : error NU1202: Package Microsoft.EntityFrameworkCore.Tools 6.0.1 is not compatible with netcoreapp2.2 (.NETCoreApp,Version=v2.2). Package Microsoft.EntityFrameworkCore.Tools 6.0.1 supports: net6.0 (.NETCoreApp,Version=v6.0) 

I also noticed that the first lines of the log stated

Info: .NET Core SDK/runtime 2.2 and 3.0 are now End of Life(EOL) and have been removed from all hosted agents. If you're using these SDK/runtimes on hosted agents, kindly upgrade to newer versions which are not EOL, or else use UseDotNet task to install the required version.
[command]"C:\Program Files\dotnet\dotnet.exe" restore D:\DevOpsAgents\some\path\Project.sln

By that time, I had verified multiple times that the projects do not use any obsolete 2.2 packages anymore. Where does the reference come from?

Then I remembered that I had experienced *some *sort of build errors, as stated above, and tried to run a dotnet restore on my development machine, disabling parallel execution and turning verbosity to full diagnostics:

dotnet restore my.project.sln --disable-parallel -v diag > dotnet-restore.log

The output is huuuge, so I piped it to a file.

Searching the generated log file for netcoreapp2.2, I finally located these lines

17:37:29.274 10:4>_GenerateDotnetCliToolReferenceSpecs: (Target-ID:26)
    TaskParameter:ToolFramework=netcoreapp2.2 (Task-ID: 17)

I found the target _GenerateDotnetCliToolReferenceSpecs in the file C:\Program Files\dotnet\sdk\6.0.101\NuGet.targets, and it sets the DotnetCliToolTargetFramework build variable to a default value if it is not set already. The default value may be, depending on your installation, netcoreapp1.0, netcoreapp2.2, or some other version.

Which part of the project would trigger an action referring to dotnet CLI tools? It’s the EF Core Tools I needed to install for database migrations:

  <ItemGroup>
	  <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.1"></DotNetCliToolReference>
  </ItemGroup>

This project setting causes dotnet to install the referenced tool, but fails to do so because the default tool framework is incompatible.

This observed behavior is documented in this GitHub issue for NuGet:

  • The DotnetCliToolTargetFramework will be interpreted by NuGet restore as the maximum target framework that tools can be restored for
  • When restoring .NET CLI tools, NuGet will first download the package, and inspect it to see what it targets. It will choose the maximum target framework the package explicitly supports that is less than or equal to the DotnetCliToolTargetFramework

This GitHub issue showed me how to set the framework version, so I added to my csproj file the following lines:

  <PropertyGroup>
    <DotnetCliToolTargetFramework>net6.0</DotnetCliToolTargetFramework>
  </PropertyGroup>

and dotnet restore worked without errors.

VS Solution Dependency Visualizer supports .NET Core Project Files

When I tried to analyze an unknown Visual Studio solution in my tool VS Solution Dependency Visualizer, I noticed that the project dependencies were not analyzed correctly. In fact, the dependencies were completely ignored.

A bit of research turned up that the solution in question was partly migrated to .NET Core, and the .csproj project files have a slightly different structure than good old .Net project files.

First, the classic .Net project files use a namespace

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

whereas .NET Core project files come without XML namespace, and have the root attribute Sdk:

<Project Sdk="Microsoft.NET.Sdk">

Also, files are not compiled if they are explicitly contained in the .csproj file, but rather by a rule-based Default Compilation mechanism which decides whether files in or below the project directory are compiled, embedded, or ignored.

For a detailed documentation of .NET Core project files, see MS docs or the dotnet GitHub docs.

The latest version of VS Solution Dependency Visualizer with support for .NET Core projects is available for download here.

BTW: In previous versions of this tool, I tried to register VS Solution Dependency Visualizer as an External Tool in all installed versions of Visual Studio.

However, things change all the time, and VS 2013 was the first version that did not support registration via registry, and with VS 2017 things got even more different, and finally I had to give up.

Instructions on how to add VS Solution Dependency Visualizer as an External Tool in your version of Visual Studio can be found in the readme file that comes with the installer.