Reputation: 83
I have a .NET solution which consists of some .NET Standard 2.0
class libraries, a few .NET Core 5.0
console apps, a .NET Framework 4.8
MVC website and .NET Framework 4.8
Web API.
We use EF Core 3.1.x
within the solution to create our database migrations which are applied to a MySql
database. We also use NuGet package Pomelo.EntityFrameworkCore.MySql 3.2.7
We have started to upgrade the .NET Framework 4.8
Web API to .NET 6
and as such have taken a dependency on OpenIddict 4.0.0
to handle authorization token generation.
OpenIddict 4.0.0
has a dependency on Microsoft.EntityFrameworkCore.Relational >= 6.0.12
which means in the upgraded .NET 6
API we are using EF Core 6.0.12
. N.B. We create a separate database to hold the OpenIddict tables in.
We therefore have 2 DbContext
derived classes MyProjectContext
and OAuthDbContext
.
MyProjectContext
lives in .NET Standard 2.0
class library MyProject.Data
which references EF Core 3.1.x
.
OAuthDbContext
lives in the upgraded .NET 6
API MyApi
which directly references EF Core 6.0.12
and Pomelo.EntityFrameworkCore.MySql 6.0.12
.
MyApi
has a project reference to MyProject.Data
as we need access to the underlying data that the API returns.
As part of the Program.cs
class in the upgraded .NET 6
API we are using Autofac
dependency injection to register existing Module
s.
One of these Module
s is the BaseModule
which looks like this:
/// <summary>
/// Autofac base module.
/// </summary>
public class BaseModule : Module
{
protected override void Load(ContainerBuilder containerBuilder)
{
// Register data layer.
// Database context.
containerBuilder.Register<DbContext>(c => new MyProjectContext()).InstancePerLifetimeScope();
// Register services.
containerBuilder.RegisterType<AccountService>().As<IAccountService>().InstancePerLifetimeScope();
//etc...
}
}
The problem I am facing is, when the upgraded .NET 6
API MyApi
is run, I get a runtime error when the MyProjectContext
default constructor is called from loading the BaseModule
, saying it cannot load Pomelo.EntityFrameworkCore.MySql version=6.0.2.0
(which is the version used in the upgraded .NET 6
API MyApi
), but the in .NET Standard 2.0
class library MyProject.Data
where the error is thrown uses Pomelo.EntityFrameworkCore.MySql version=3.2.7.0
.
System.TypeLoadException
HResult=0x80131522
Message=Could not load type 'Microsoft.EntityFrameworkCore.MySqlDbContextOptionsExtensions' from assembly 'Pomelo.EntityFrameworkCore.MySql, Version=6.0.2.0, Culture=neutral, PublicKeyToken=2cc498582444921b'.
Source=MyProject.Data
StackTrace:
at MyProject.Data.MyProjectContext.GetMySQLContextOptions(String connectionString) in C:\Users\Adrian\source\repos\myproject\myproject\MyProject.Data\MyProjectObjectContext.cs:line 60
at MyProject.Data.MyProjectContext..ctor() in C:\Users\username\source\repos\myproject\myproject\MyProject.Data\MyProjectObjectContext.cs:line 18
at MyProject.Framework.DIModules.BaseModule.<>c.<Load>b__0_0(IComponentContext c) in C:\Users\username\source\repos\myproject\myproject\MyProject.Framework\DIModules\BaseModule.cs:line 53
at Autofac.RegistrationExtensions.<>c__DisplayClass41_0`1.<Register>b__0(IComponentContext c, IEnumerable`1 p)
at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass0_0`1.<ForDelegate>b__0(IComponentContext c, IEnumerable`1 p)
at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
at Autofac.Core.Activators.Delegate.DelegateActivator.<ConfigurePipeline>b__2_0(ResolveRequestContext ctxt, Action`1 next)
at Autofac.Core.Resolving.Middleware.DelegateMiddleware.Execute(ResolveRequestContext context, Action`1 next)
at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
at Autofac.Core.Resolving.Middleware.DisposalTrackingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
Is it possible to use two different versions of EF Core
in referenced projects?
Upvotes: 0
Views: 520
Reputation: 5254
The issue here is that OpenIddict
assumes you want to use EF Core 6
if you target net6.0
, even though it is perfectly fine to use EF Core 3.1
with net6.0
.
One way to solve this should be to just build the OpenIddict 4.0.0
repository locally.
You should then be able to reference the built netcoreapp3.1
assemblies from your MyApi
project.
Your MyApi
project would then target net6.0
, reference the locally built netcoreapp3.1
assemblies of OpenIddict 4.0.0
and use EF Core 3.1
(via package reference).
Your MyProject.Data
project would target netstandard2.0
and use EF Core 3.1
(via package reference).
(Instead of using the netcoreapp3.1
assemblies of OpenIddict
, you could of course also just change the code of OpenIddict
to make it reference EF Core 3.1
when targeting net6.0
, in which case you MyApi
project would just reference the net6.0
assemblies of OpenIddict
).
Another way is to use multi-targeting for your MyProject.Data
project.
You would need some preprocessor conditions around your UseMySql()
call, because the signature changed between Pomelo 3.1 and 5.0 (a mandatory server version parameter was added).
Your MyApi
project would target net6.0
, OpenIddict 4.0.0
(via package reference) and use EF Core 6.0
(via package reference).
Your MyProject.Data
project would target netstandard2.0
and use EF Core 3.1
(via package reference) and also target net6.0
and use EF Core 6.0
(via package reference).
Upvotes: 1