Search code examples
c#entity-framework-6entity-framework-migrationsassembly-loadingmicrosoft-data-sqlclient

Why is Microsoft.Data.SqlClient throwing TypeInitializationException when loading Microsoft.Identity.Client at runtime?


I have an Entity Framework 6 model (code-first, with migrations enabled and auto-migrations disabled) in a class library that targets .NET 4.8 and .NET Standard 2.1 (AnyCPU). This is an SDK-style .csproj file. It's multi-targeted so I can use the same model in both .NET Framework and .NET Core projects, which is also the reason why the model uses EF6 instead of EF Core.

<PropertyGroup>
    <TargetFrameworks>net48;netstandard2.1</TargetFrameworks>
</PropertyGroup>

In the same solution, I have a .NET Framework 4.8 x64 WPF application which consumes the EF 6 model class library via a Project Reference. This is an old-style .csproj project, not SDK-style, since it's a WPF project targeting .NET 4.8 (only). This project has "Auto-generate binding redirects" enabled. This project must target .NET 4.8 because it has other dependencies which are not available for .NET 5+, and targets x64 rather than AnyCPU because it uses P/Invoke interop to an x64 C++ DLL.

Both the class library and the WPF application projects have the Microsoft.EntityFramework.SqlServer v6.5.1 NuGet package installed, which pulls in the EntityFramework v6.5.1 and Microsoft.Data.SqlClient v5.1.5 NuGet packages as transitive dependencies. Microsoft.Data.SqlClient depends on Microsoft.Identity.Client >= 4.56.0 and Azure.Identity >= 1.10.3.

I have upgraded Azure.Identity to 1.13.2 (currently the latest) because all versions older than 1.11.4 have been flagged as vulnerable. Upgrading Azure.Identity also upgrades Microsoft.Identity.Client to v4.67.2. The same version of both packages is installed in both projects.

I'm trying to use Update-Database to apply my code-first migrations to my database. I've selected the WPF application as the solution's debug startup project, and the EF 6 model class library is selected as the "Default project" in the NuGet Package Manager console where I'm running the Update-Database PowerShell command.

When I run Update-Database, I get the following exception:

System.TypeInitializationException: The type initializer for 'Microsoft.Data.SqlClient.SqlAuthenticationProviderManager' threw an exception.
System.IO.FileLoadException: Could not load file or assembly 'Microsoft.Identity.Client, Version=4.56.0.0, Culture=neutral, PublicKeyToken=0a613f4dd989e8ae' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

It looks like the Microsoft.Data.SqlClient assembly is rejecting the updated version of Microsoft.Identity.Client, even though it should be a compatible version according to the NuGet package dependency requirements.

If I downgrade Azure.Identity to v1.10.3 (which transitively allows Microsoft.Identity.Client to downgrade to v4.56.0, which is also flagged as vulnerable), I no longer get the assembly loading exceptions.

I'm not keen on having known vulnerable packages in my project, though. Why would these assembly load failures be happening when I have "Auto-generate binding redirects" turned on? Is there a way I can fix it other than accepting the vulnerable packages?


Solution

  • Ah, it looks like this error is due to a known issue with the Microsoft.Data.SqlClient package's dependency configuration, and Entity Framework is not at fault except insofar as its current NuGet package release depends on a slightly out-of-date version of Microsoft.Data.SqlClient.

    I was able to remove the known-vulnerable packages by upgrading Microsoft.Data.SqlClient to 5.2.2, which upgraded Azure.Identity to 1.11.4 and Microsoft.Identity.Client to 4.61.3.