dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.61k stars 3.14k forks source link

FileLoadException: System.Runtime v6.0.0 when using scaffolder with latest dotnet-7 feed dotnet-ef tool. #27660

Closed AraHaan closed 2 years ago

AraHaan commented 2 years ago

File a bug

When trying to scaffold my database using text templates, the resulting is an FileLoadException after build succeeds.

Include your code

The following is my project files (excluding code and sensitive information):

csproj:

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

Directory.Build.props:

<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <PropertyGroup>
    <!--
    For non-SDK projects that import this file and then import Microsoft.Common.props,
    tell Microsoft.Common.props not to import Directory.Build.props again
    -->
    <ImportDirectoryBuildProps>false</ImportDirectoryBuildProps>
  </PropertyGroup>

  <PropertyGroup>
    <RootNamespace>MyBot.Database</RootNamespace>
    <TargetFramework>net6.0</TargetFramework>
    <OutputPath>..\bin\$(Configuration)\</OutputPath>
    <SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <LangVersion>preview</LangVersion>
    <Version>2.1.100</Version>
    <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
    <EnableNETAnalyzers>true</EnableNETAnalyzers>
    <AnalysisLevel>preview</AnalysisLevel>
    <AnalysisMode>AllEnabledByDefault</AnalysisMode>
    <IsPackable>false</IsPackable>
    <DebugType>embedded</DebugType>
  </PropertyGroup>

</Project>

Directory.Build.targets:

<Project>

  <ItemGroup>
    <!-- We do not need these global usings. -->
    <Using Remove="System.Net.Http" />
    <Using Remove="System.Threading" />
    <!-- We need to also add these global usings. -->
    <Using Include="System.ComponentModel.DataAnnotations" />
    <Using Include="System.ComponentModel.DataAnnotations.Schema" />
    <Using Include="System.Globalization" />
    <Using Include="CsvHelper" />
    <Using Include="Microsoft.EntityFrameworkCore" />
    <Using Include="Microsoft.EntityFrameworkCore.Metadata.Builders" />
    <Using Include="Microsoft.Extensions.DependencyInjection" />
    <Using Include="MyBot.Database.Extensions" />
    <InternalsVisibleTo Include="MyBot.Discord" />
    <None Update="CodeTemplates/EFCore/DbContextGenerator.t4">
      <Link>Model/DbContextGenerator.t4</Link>
    </None>
    <None Update="CodeTemplates/EFCore/EntityTypeGenerator.t4">
      <Link>Model/EntityTypeGenerator.t4</Link>
      <DependentUpon>DbContextGenerator.t4</DependentUpon>
    </None>
    <Compile Update="Model/BotDbContext.cs">
      <DependentUpon>DbContextGenerator.t4</DependentUpon>
      <AutoGen>True</AutoGen>
    </Compile>
    <Compile Update="Model/BotDbContext.Methods.cs">
      <DependentUpon>BotDbContext.cs</DependentUpon>
    </Compile>
    <Compile Update="Model/DiscordToken.cs">
      <DependentUpon>EntityTypeGenerator.t4</DependentUpon>
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
    </Compile>
    <Compile Update="Model/ExpiringVerification.cs">
      <DependentUpon>EntityTypeGenerator.t4</DependentUpon>
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
    </Compile>
    <Compile Update="Model/Patron.cs">
      <DependentUpon>EntityTypeGenerator.t4</DependentUpon>
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
    </Compile>
    <Compile Update="Model/Role.cs">
      <DependentUpon>EntityTypeGenerator.t4</DependentUpon>
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
    </Compile>
    <Compile Update="Model/Tier.cs">
      <DependentUpon>EntityTypeGenerator.t4</DependentUpon>
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
    </Compile>
  </ItemGroup>

</Project>

Directory.Packages.props:

<Project>

  <ItemGroup>
    <PackageReference Include="IDisposableAnalyzers" Version="*-*">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="*-*" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="*-*">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>
    <PackageReference Include="CsvHelper" Version="*-*" />
  </ItemGroup>

</Project>

nuget.config feeds:

Include stack traces

System.IO.FileLoadException: Could not load file or assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
   at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type, ObjectHandleOnStack keepAlive)
   at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
   at Microsoft.EntityFrameworkCore.Tools.ReflectionOperationExecutor..ctor(String assembly, String startupAssembly, String projectDir, String dataDirectory, String rootNamespace, String language, Boolean nullable, String[] remainingArguments)
   at Microsoft.EntityFrameworkCore.Tools.Commands.ProjectCommandBase.CreateExecutor(String[] remainingArguments)
   at Microsoft.EntityFrameworkCore.Tools.Commands.DbContextScaffoldCommand.Execute(String[] args)
   at Microsoft.DotNet.Cli.CommandLine.CommandLineApplication.Execute(String[] args)
   at Microsoft.EntityFrameworkCore.Tools.Program.Main(String[] args)

Include verbose output

Please include --verbose output when filing bugs about the dotnet ef or Package Manager Console tools.

Use triple-tick fences for tool output. For example:

Using project 'H:\Desktop\github\MyBot\MyBot.Database\MyBot.Database.csproj'.
Using startup project 'H:\Desktop\github\MyBot\MyBot.Database\MyBot.Database.csproj'.
Writing 'H:\Desktop\github\MyBot\MyBot.Database\obj\MyBot.Database.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\User\AppData\Local\Temp\tmp8ECD.tmp /verbosity:quiet /nologo "H:\Desktop\github\MyBot\MyBot.Database\MyBot.Database.csproj"
Writing 'H:\Desktop\github\MyBot\MyBot.Database\obj\MyBot.Database.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\User\AppData\Local\Temp\tmp9BAF.tmp /verbosity:quiet /nologo "H:\Desktop\github\MyBot\MyBot.Database\MyBot.Database.csproj"
Build started...
dotnet build "H:\Desktop\github\MyBot\MyBot.Database\MyBot.Database.csproj" /verbosity:quiet /nologo

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:15.72
Build succeeded.
dotnet exec --depsfile "H:\Desktop\github\MyBot\bin\net6.0\MyBot.Database.deps.json" --additionalprobingpath C:\Users\User\.nuget\packages --additionalprobingpath "C:\Users\User\Desktop\VS2017 Preview\Shared\NuGetPackages" --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" C:\Users\User\.nuget\packages\dotnet-ef\7.0.0-preview.3.22159.9\tools\netcoreapp3.1\any\tools\netcoreapp2.0\any\ef.dll dbcontext list --assembly "H:\Desktop\github\MyBot\bin\net6.0\MyBot.Database.dll" --project "H:\Desktop\github\MyBot\MyBot.Database\MyBot.Database.csproj" --startup-assembly "H:\Desktop\github\MyBot\bin\net6.0\MyBot.Database.dll" --startup-project "H:\Desktop\github\MyBot\MyBot.Database\MyBot.Database.csproj" --project-dir "H:\Desktop\github\MyBot\MyBot.Database\\" --root-namespace MyBot.Database --language C# --framework net6.0 --nullable --working-dir "H:\Desktop\github\MyBot" --verbose
Using assembly 'MyBot.Database'.
Using startup assembly 'MyBot.Database'.
Using application base 'H:\Desktop\github\MyBot\bin\net6.0'.
Using working directory 'H:\Desktop\github\MyBot\MyBot.Database'.
Using root namespace 'MyBot.Database'.
Using project directory 'H:\Desktop\github\MyBot\MyBot.Database\'.
Remaining arguments: .
System.IO.FileLoadException: Could not load file or assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
   at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type, ObjectHandleOnStack keepAlive)
   at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
   at Microsoft.EntityFrameworkCore.Tools.ReflectionOperationExecutor..ctor(String assembly, String startupAssembly, String projectDir, String dataDirectory, String rootNamespace, String language, Boolean nullable, String[] remainingArguments)
   at Microsoft.EntityFrameworkCore.Tools.Commands.ProjectCommandBase.CreateExecutor(String[] remainingArguments)
   at Microsoft.EntityFrameworkCore.Tools.Commands.DbContextListCommand.Execute(String[] args)
   at Microsoft.DotNet.Cli.CommandLine.CommandLineApplication.Execute(String[] args)
   at Microsoft.EntityFrameworkCore.Tools.Program.Main(String[] args)

Include provider and version information

EF Core version: Latest on dotnet-7 feed. Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET 6 Operating system: Windows IDE: Visual Studio 2022 17.2 Preview 2

AraHaan commented 2 years ago

cc: @ajcvickers this is a blocking issue for me.

AraHaan commented 2 years ago

I just tested this with updating the runtimes manually and it still does not work.

Edit: changed tfm to net 7 and still it fails with the exact same error, it seems the tool itself is broken somewhere.

AraHaan commented 2 years ago

This looks to be an issue where something might be referencing the System.Runtime.Experimental package or w/e it's name is.

AraHaan commented 2 years ago

Ah It might be the references in Microsoft.Data.SqlClient biting me (it's reference to System.IO which references an outdated System.Runtime.

According to PerfView: the only thing asking for System.Runtime v6 on this is: System.CommandLine, otherwise the tool uses the .NET 7 copy.

roji commented 2 years ago

@AraHaan can this be closed or do you still think there's an EF Core issue here?

AraHaan commented 2 years ago

Honestly I am not entirely sure if CommandLine is the root, as well I ran it with dotnet trace and it would not self exit the program without me pressing enter (to have dotnet trace terminate it) 10 minutes later. So it is possible that PerfView might have wrong data.

roji commented 2 years ago

@AraHaan we'd need a minimal project which reproduces the problem in order to investigate this.

AraHaan commented 2 years ago

I will work on that as soon as I get back to my computer.

AraHaan commented 2 years ago

Alright got it done:

MyBot.Database.zip (I minimalized it to just the small db and sql code to run so the scaffolder can try to scaffold it)

As for the command it's: dotnet ef dbcontext scaffold "Data Source=(local)\SQLEXPRESS;Initial Catalog=Bot;Integrated Security=True;Encrypt=True;TrustServerCertificate=True;User Instance=False" Microsoft.EntityFrameworkCore.SqlServer -t DiscordToken -t ExpiringVerifications -t Patrons -t Roles -t Tiers --use-database-names --data-annotations -c BotDbContext --context-dir Model -o Model -n MyBot.Database --no-onconfiguring -f -s "MyBot.Database.csproj" -p "MyBot.Database.csproj"

AraHaan commented 2 years ago

Ah, when I tested again with all the other runtimes, ref packs to them, and the Sdk's that are not 6.0.200/6.0.300-preview it results in this on the command I sent above:

It was not possible to find any compatible framework version
The framework 'Microsoft.NETCore.App', version '2.0.0' (x64) was not found.
  - The following frameworks were found:
      6.0.3 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

When 2.0.9's runtime is installed, it results in the FileLoadException for 6.0.0's System.Runtime. It seems for some reason the tool wants to require 2.0.0, but then tries to roll forward to 6.0.0 and fail.

AraHaan commented 2 years ago

Ok, so I have tested and that https://github.com/dotnet/efcore/pull/27671 does infact fix this issue.

ajcvickers commented 2 years ago

/cc @bricelam

bricelam commented 2 years ago

Is this really your entire project file?

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

How are you referencing the EFCore packages? How are you running the commands?

This error is usually only seen in extreme corner cases where the .runtime.json file doesn't get generated on build.

AraHaan commented 2 years ago

@bricelam I reference the packages in Directory.Packages.props, build settings in Directory.Build.props, and <ItemGroup> items in Directory.Build.targets.

ajcvickers commented 2 years ago

@AraHaan Is there some reason for going down this path instead of using the daily build?

AraHaan commented 2 years ago

I thought the dotnet-7 freed versions were the daily builds of dotnet-ef?

Also even with the daily build of the .NET runtime it was asking for the 6.0.0 version of System.Runtime before the roll forward patch on the tool called by dotnet-ef.

ajcvickers commented 2 years ago

@AraHaan If the tooling doesn't work with the 6.0 runtime/SDK installed by the time we ship, then that would be problem. But its early days, so for now, just have 6.0 installed. EF Core 7.0 targets .NET 6.0 anyway, so there is no need to use it with 7.0.

AraHaan commented 2 years ago

I tried the preview 5 tool just now and still have this issue.

It seems that RollForward was not enough to fix the issue somehow.

https://github.com/dotnet/efcore/commit/06b2b1f75fbfd16501d2b6bfec6d0374cf203b03

Looks the only option now is to drop on the src/ef folder all TFM's that are not .NET 6 so that way the tool starts working again.

AraHaan commented 2 years ago

Yep changing the src/ef project from netcoreapp2.0 to net6.0 fixed the problem permanently.

Note: I did not drop the .NET Framework target at all to prevent possible breaking changes.