EF Core 2.1.4 FileLoadException System.ComponentModel.Annotations 4.2.0.0

3

After upgrading our data access layer from EF6 to EF Core 2.1(.4) we are having trouble with a FileLoadException with System.ComponentModel.Annotations, Version=4.2.0.0, which is odd since EF Core 2.1.4 uses 4.5.0.0, and nothing else (we can find) in our solution uses 4.2.0.0.

Say for example we have the following project structure in our solution:

DataAccess: (all projects using Microsoft.EntityFrameworkCore.SqlServer Version 2.1.4)
- Models (Only the models created with Scaffold-DbContext)
- Core (Abstract providers, persisters, etc.)
- Common (DTOs, concrete providers, persisters, etc.)

Main Solution: (no projects have EF Core package installed)
- Some project (A) with project references to Models, Core, Common

Even if project A is, for example, a simple console app that just loads something from the database and displays it to the console, when something is evaluated at the abstract provider level in DataAccess.Core, we get the following exception:

System.IO.FileLoadException occurred HResult=0x80131040 Message=Could not load file or assembly 'System.ComponentModel.Annotations, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

What is strange is that we can't find System.ComponentModel.Annotations, Version=4.2.0.0 anywhere, the version is even skipped in Nuget.
Trying the accepted answer in this question: Could not load file or assembly 'System.ComponentModel.Annotations, Version=4.1.0.0 , by adding the following to my .csproj files seems to fix the issue for some projects, but not all:

<PropertyGroup>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

In the generated DataAccess.Models.dll.config files after building the only reference to System.ComponentModel.Annotations is the following:

<dependentAssembly>
  <assemblyIdentity name="System.ComponentModel.Annotations" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.2.1.0" />
</dependentAssembly>

Which isn't 4.2.0.0, but we're not sure where that new version number is being decided on. It's probably something minor we've missed or incorrectly configured, but some assistance in finding the issue or pointers on where to look would be appreciated. A solution where we don't have to add AutoGenerateBindingRedirects to every .csproj file would be ideal

c#
.net
entity-framework
ef-core-2.1
asked on Stack Overflow Oct 9, 2018 by JChristen

2 Answers

0

Content from @JRB's comment, formatted as an answer for readability:

This is an existing problem that seems difficult for Microsoft to fix, possibly because it involves cooperation between multiple development groups. It only occurs in some more complex solutions. The solution is quiet simple. Change the bindingRedirect from

<bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.2.1.0" />

to

<bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.0.0.0" />

and the chances are quiet reasonable that your problem goes away. This bindingredirect can be automaticlly applied in multiple projects. Tests which one(s) are causing your problem.

answered on Stack Overflow Mar 13, 2019 by JChristen
0

I had the same issue. I have solved it by implementing the following helper function redirecting the assembly at the begin (which was suggested in this answer):

public static class FunctionsAssemblyResolver
{
    #region Public Methods

    public static void RedirectAssembly()
    {
        AppDomain.CurrentDomain.AssemblyResolve += ResolveAssemblyOnCurrentDomain;
    }

    #endregion Public Methods

    #region Private Methods

    private static Assembly ResolveAssemblyOnCurrentDomain(object sender, ResolveEventArgs args)
    {
        var requestedAssembly = new AssemblyName(args.Name);
        var assembly = default(Assembly);

        AppDomain.CurrentDomain.AssemblyResolve -= ResolveAssemblyOnCurrentDomain;

        try
        {
            assembly = Assembly.Load(requestedAssembly.Name);
        }
        catch
        { }

        AppDomain.CurrentDomain.AssemblyResolve += ResolveAssemblyOnCurrentDomain;

        return assembly;
    }

    #endregion Private Methods
}
answered on Stack Overflow Feb 3, 2020 by budul

User contributions licensed under CC BY-SA 3.0