0

When I attempt to upgrade EF Core from 6.0.0 to v6.0.1 (to fix an showstopping NullReferenceException deep in the bowels of HasForeignKey), our database project compiles successfully. However, our company's main Web API project does not:

------ Rebuild All started: Project: CompanyWebApi, Configuration: Debug Any CPU ------
...MSB3277: Found conflicts between different versions of "Microsoft.EntityFrameworkCore" that could not be resolved.
...MSB3277: There was a conflict between "Microsoft.EntityFrameworkCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60" and "Microsoft.EntityFrameworkCore, Version=6.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60".
...MSB3277:     "Microsoft.EntityFrameworkCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60" was chosen because it was primary and "Microsoft.EntityFrameworkCore, Version=6.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60" was not.
...MSB3277:     References which depend on "Microsoft.EntityFrameworkCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60" [C:\...\.nuget\packages\microsoft.entityframeworkcore\6.0.0\lib\net6.0\Microsoft.EntityFrameworkCore.dll].
...MSB3277:         C:\...\.nuget\packages\microsoft.entityframeworkcore\6.0.0\lib\net6.0\Microsoft.EntityFrameworkCore.dll
...MSB3277:           Project file item includes which caused reference "C:\...\.nuget\packages\microsoft.entityframeworkcore\6.0.0\lib\net6.0\Microsoft.EntityFrameworkCore.dll".
...MSB3277:             C:\...\.nuget\packages\microsoft.entityframeworkcore\6.0.0\lib\net6.0\Microsoft.EntityFrameworkCore.dll
...MSB3277:     References which depend on "Microsoft.EntityFrameworkCore, Version=6.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60" [].
...MSB3277:         C:\Dev\CompanyServer\CompanyDB\bin\Debug\net6.0\CompanyDB.dll
...MSB3277:           Project file item includes which caused reference "C:\Dev\CompanyServer\CompanyDB\bin\Debug\net6.0\CompanyDB.dll".
...MSB3277:             C:\Dev\CompanyServer\CompanyDB\bin\Debug\net6.0\CompanyDB.dll
...
CSC : error CS1705: Assembly 'CompanyDB' with identity 'CompanyDB, Version=1.0.0.0...' uses 'Microsoft.EntityFrameworkCore, Version=6.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' which has a higher version than referenced assembly 'Microsoft.EntityFrameworkCore' with identity 'Microsoft.EntityFrameworkCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'
Done building project "CompanyWebApi.csproj" -- FAILED.

The thing is, our Web API project does not reference EF Core (or anything that depends on it AFAIK), so this conflict should not be possible. And as you can see, neither the warning messages nor the error message even claims that the Web API project has a reference to EntityFrameworkCore. In fact, the warning message seems to claim that 6.0.0\lib\net6.0\Microsoft.EntityFrameworkCore.dll "caused" a reference to itself! (or rather a nonexistent "Project file item" caused the reference, and indeed every time I've seen this warning, it talks about a "Project file item" that doesn't exist.)

Note: in our project, transitive references are disabled via the magic Directory.Build.props file located in the same directory as the solution:

<!-- Turn off transitive dependencies to enforce separation of concerns.
    In particular, ASP.NET UI/HTTP code should not directly use anything from Entity Framework Core.
-->
<Project>
  <PropertyGroup>    
    <DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences>
  </PropertyGroup>
</Project>

My main question is this: what process should I follow to track down the cause of this error?

Another question: how does the build system decide whether a conflict is treated as an error or just a warning? (In the past, I have gotten the warning without the error.)

If anyone wants to guess what's causing the problem in my specific case, here are the project files for the DB and for the Web API respectively.

<!-- DB project (builds fine) -->
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <LangVersion>10.0</LangVersion>
    <Nullable>enable</Nullable>
    <RootNamespace>Company</RootNamespace>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Assisticant" Version="1.5.7" />
    <PackageReference Include="EFCore.NamingConventions" Version="6.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
    <PackageReference Include="Nito.AsyncEx.Coordination" Version="5.1.2" />
    <PackageReference Include="Npgsql" Version="6.0.0" />
    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite" Version="6.0.0" />
    <PackageReference Include="System.Text.Json" Version="6.0.1" />
    <PackageReference Include="NetTopologySuite.IO.GeoJSON4STJ" Version="2.1.1" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\CompanyCommon\CompanyCommon.csproj" />
    <ProjectReference Include="..\AllPurpose\AllPurpose.csproj" />
  </ItemGroup>
</Project>

<!-- Web API project (errors) -->
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
    <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
    <IsPackable>false</IsPackable>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <LangVersion>10.0</LangVersion>
    <Nullable>enable</Nullable>
    <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <Optimize>true</Optimize>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="6.0.1" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.1" />
    <!--<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.1.9" />-->
    <PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.OData" Version="8.0.4" />
    <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="6.0.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.1" />
    <PackageReference Include="Microsoft.Identity.Web" Version="1.14.0" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\AllPurpose\AllPurpose.csproj" />
    <ProjectReference Include="..\CompanyCommon\CompanyCommon.csproj" />
    <ProjectReference Include="..\CompanyDB\CompanyDB.csproj" />
  </ItemGroup>
</Project>

Things I tried that didn't work:

  • "Clean" and "Rebuild all"
  • I cannot simply remove references to find out which reference is causing the problem, because removing any reference has the same effect: the CS1705 error is replaced with compiler errors.
  • As a workaround for the previous fact of life, I tried creating a new empty (console app) project "WebApi2" and then replacing the contents of that project with the contents of the real WebApi project. I was hoping that this would allow me to freely remove references from "WebApi2" one-by-one to find out which one of the references was causing the problem. Sadly, WebApi2 has MSB3277 warnings but no CS1705!
Qwertie
  • 16,354
  • 20
  • 105
  • 148
  • Have you tried removing the reference to duplicates in web.config file altogether? Sometimes I found older versions listed in web.config file that generates these errors – Jawad Jan 07 '22 at 04:50
  • @Jawad there are no "web.config" files in the solution, and I don't know what "duplicates" you mean. – Qwertie Jan 07 '22 at 04:53
  • Though you say nothing pulls it in, it may be another package's package, etc...I suggest check each the nuget packages properties for the project and set any packages that specify `least version` to `[get] the latest` version; to see if that helps. See my answer here https://stackoverflow.com/a/36344325/285795 – ΩmegaMan Jan 07 '22 at 05:00

1 Answers1

2

In my case, it turned out that

  1. The WebAPI project that doesn't reference EF Core was using an extension method called SingleOrDefaultAsync(). Apparently this method is part of Microsoft.EntityFrameworkCore, and somehow the code was able to use the extension method without a using Microsoft.EntityFrameworkCore directive. IntelliSense does not show a red squiggly under the call to SingleOrDefaultAsync() but it's colored as if it is not recognized, and F12 causes VS to say "Cannot navigate to the symbol under the caret." This "impossible" method call was enough to trigger the CS1705 error.
  2. The WebAPI project calls method UpgradeOrCreateDatabase() in the database project with no arguments, but there is a default parameter Action<CompanyDbContext>? postUpgradeAction = null, and CompanyDbContext is derived from EF Core's DbContext class. This is enough to trigger the CS1705 error. As a workaround I created another overload that genuinely has no parameters.

Obviously, it was hard to figure out which specific lines of code (among thousands) triggered the error, and it's probably not worth explaining the laborious process I used. Once those issues were fixed, the CS1705 error disappeared but the MSB3277 warnings remained.

Luckily I did discover a workaround that removes both the error and the warnings: just copy the EF Core reference from the database project to the Web API project:

    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>

Your mileage may vary and this solution is clearly wrong since the Web API project is not supposed to access EF Core, but at least it unblocks me.

Fun fact: remember that call to SingleOrDefaultAsync from before? Adding a reference to EF Core actually caused a compiler error: "IQueryable<FileContentDBO> does not contain a definition for SingleOrDefaultAsync". This was easily fixed by adding a using Microsoft.EntityFrameworkCore directive.

Qwertie
  • 16,354
  • 20
  • 105
  • 148
  • Generally speaking, you shouldn't [reference Microsoft.EntityFrameworkCore.Design](https://learn.microsoft.com/en-us/ef/core/cli/services#referencing-microsoftentityframeworkcoredesign) package as it is not supposed to be included in the deployment. And even if you do so in the DB project (for some reason), always add explicit reference to the desired version of `Microsoft.EntityFrameworkCore` which is the "primary" EF Core package. – Ivan Stoev Jan 07 '22 at 07:51
  • @IvanStoev the DB project must reference it, or `dotnet ef migrations` won't work, saying "Your startup project doesn't reference Microsoft.EntityFrameworkCore.Design. This package is required for the Entity Framework Core Tools to work." Maybe I should also have a reference to `Microsoft.EntityFrameworkCore` but it doesn't seem to make a difference. – Qwertie Jan 07 '22 at 15:39