I have a solution in which we have two DbContexts, and we are in the process of moving from EF4 to EF6. The older DbContext was a code-first and we are mostly using the newer generated db-first, but need both in operation due to external dependencies.
My classes look like this:
namespace Old.Busted.EF.DAL
{
[DbConfigurationType(typeof(Old.Busted.EF.DAL.OldConfiguration))]
public class OldContext : DbContext[...]
public class OldConfiguration : DbConfiguration[...]
}
namespace New.Shiny.EF.DAL
{
[DbConfigurationType(typeof(New.Shiny.EF.DAL.NewConfiguration))]
public class NewContext : DbContext[...]
public class NewConfiguration : DbConfiguration[...]
}
The precise error that I am getting is
An instance of 'NewConfiguration' was set but this type was not discovered in the same assembly as the 'OldContext' context. Either put the DbConfiguration type in the same assembly as the DbContext type, use DbConfigurationTypeAttribute on the DbContext type to specify the DbConfiguration type, or set the DbConfiguration type in the config file.
which is trying to apply the new configuration to the old context. The library in which the breaking code is sitting is the only library which references both the old and new EF DALs, and moreover this exception only gets thrown when the tests are being run on the command line via mstest - they pass just fine running from within Visual Studio.
Using .NET 4.0 and Visual Studio 2010.
Things I have tried:
Easiest solution seems to have been to move to config-file based configuration, as detailed here.
The reason I couldn't get this to work the first time is because I had a different version of EF listed in one of the various config files and didn't catch it.
I did try using a single DbConfiguration class in a common library and was able to get it to work this time (with no real fiddling, I must have just done something terribly wrong the first time) but I think that the config-file based configuration is the better solution.
Putting configuration information in a config file, how novel!
According to Microsoft you can solve two DbContexts with DbConfiguration
like this:
XML:
<entityFramework codeConfigurationType="MyNamespace.MyDbConfiguration, MyAssembly">
...Your EF config...
</entityFramework>
Code:
[DbConfigurationType(typeof(MyDbConfiguration))]
public class MyContextContext : DbContext
{
}
[DbConfigurationType("MyNamespace.MyDbConfiguration, MyAssembly")]
public class MyContextContext : DbContext
{
}
https://docs.microsoft.com/en-us/ef/ef6/fundamentals/configuring/code-based
I did not solve multiple DbConfiguration
however. My solution was sharing the same DbConfiguration
for both DbContexts like this:
public class DbContextConfiguration : DbConfiguration
{
public DbContextConfiguration()
{
var providerInstance = SqlProviderServices.Instance;
SqlProviderServices.TruncateDecimalsToScale = false;
this.SetProviderServices(SqlProviderServices.ProviderInvariantName, SqlProviderServices.Instance);
}
}
[DbConfigurationType(typeof(DbContextConfiguration))]
public class DbContext1 : DbContext
{
}
[DbConfigurationType(typeof(DbContextConfiguration))]
public class DbContext2 : DbContext
{
}
Multiple DbContext classes WITHOUT configuration file (except for connectionStrings):
You only need to add [DbConfigurationType(typeof(CodeFirstDbConfiguration))]
to every class that inherits the DbContext
class.
It uses Reflection. I don't mind that :)
Please check it out!
Depending on the C# or the .NET versions, you may need to a few some lines of code (e.g., from is not null
to != null
)
App.config:
No need to specify the entityFramework configSection!
No need to specify the entityFramework providers!
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<clear/>
<add name="Foo_MySqlDbContext"
connectionString="Server=yyy ; Database=yyy ; Uid=yyy ; Pwd=yyy ; Connect Timeout=30 ; SslMode=none ;"
providerName="MySql.Data.MySqlClient" />
<add name="Foo_NpgsqlDbContext"
connectionString="Server=yyy ; Port=yyy ; Database=yyy ; UserId=yyy ; Password=yyy ;"
providerName="Npgsql" />
</connectionStrings>
</configuration>
ConsoleApp1.csproj:
Does NOT need to target NET 6.0
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EntityFramework" Version="6.4.4" />
<PackageReference Include="EntityFramework6.Npgsql" Version="6.4.3" />
<PackageReference Include="MySql.Data" Version="8.0.18" />
<PackageReference Include="MySql.Data.EntityFramework" Version="8.0.18" />
<PackageReference Include="Npgsql" Version="5.0.10" />
</ItemGroup>
</Project>
Program.cs:
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Core.Common;
using System.Reflection;
namespace ConsoleApp1
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Foo_NpgsqlDbContext");
try
{
using (var db = new Foo_NpgsqlDbContext())
Console.WriteLine("Exists : " + db.Database.Exists());
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
Console.WriteLine();
Console.WriteLine("Foo_MySqlDbContext");
try
{
using (var db = new Foo_MySqlDbContext())
Console.WriteLine("Exists : " + db.Database.Exists());
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
Console.ReadLine();
}
}
[DbConfigurationType(typeof(CodeFirstDbConfiguration))]
public class Foo_NpgsqlDbContext : DbContext
{
public Foo_NpgsqlDbContext()
: base("name=Foo_NpgsqlDbContext") { }
}
[DbConfigurationType(typeof(CodeFirstDbConfiguration))]
public class Foo_MySqlDbContext : DbContext
{
public Foo_MySqlDbContext()
: base("name=Foo_MySqlDbContext") { }
}
/// <summary>
/// usage:
/// [DbConfigurationType(typeof(CodeFirstDbConfiguration))]
/// </summary>
public class CodeFirstDbConfiguration
: System.Data.Entity.DbConfiguration
{
private static bool _initialized = false;
public CodeFirstDbConfiguration()
{
if (_initialized) return;
_initialized = true;
//return; // Uncomment to make the application NOT work
ConfigureMySql();
ConfigureOracle();
ConfigurePostgreSql();
ConfigureSqlServer();
//Configure...(); // configure other database kinds
}
#region MySql
private void ConfigureMySql()
{
var services = Type.GetType("MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.EntityFramework")
?.GetConstructor(Array.Empty<Type>())
?.Invoke(null) as DbProviderServices;
if (services is not null)
SetProviderServices("MySql.Data.MySqlClient", services);
if (DbProviderFactories.GetProviderInvariantNames().Contains("MySql.Data.MySqlClient") == false)
DbProviderFactories.RegisterFactory(
"MySql.Data.MySqlClient",
"MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=8.0.18.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"
);
}
#endregion
#region Oracle
private void ConfigureOracle()
{
var services = Type.GetType("Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework")
?.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, Array.Empty<Type>())
?.Invoke(null) as DbProviderServices;
if (services is not null)
SetProviderServices("Oracle.ManagedDataAccess.Client", services);
if (DbProviderFactories.GetProviderInvariantNames().Contains("Oracle.ManagedDataAccess.Client") == false)
DbProviderFactories.RegisterFactory(
"Oracle.ManagedDataAccess.Client",
"Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.122.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342"
);
}
#endregion
#region PostgreSql
private void ConfigurePostgreSql()
{
var services = Type.GetType("Npgsql.NpgsqlServices, EntityFramework6.Npgsql")
?.GetConstructor(Array.Empty<Type>())
?.Invoke(null) as DbProviderServices;
if (services is not null)
SetProviderServices("Npgsql", services);
var factory = Type.GetType("Npgsql.NpgsqlFactory, Npgsql")
?.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, Array.Empty<Type>())
?.Invoke(null) as DbProviderFactory;
if (factory is not null)
SetProviderFactory("Npgsql", factory);
if (DbProviderFactories.GetProviderInvariantNames().Contains("Npgsql") == false)
DbProviderFactories.RegisterFactory(
"Npgsql",
"Npgsql.NpgsqlFactory, Npgsql, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7"
);
}
#endregion
#region SqlServer
private void ConfigureSqlServer()
{
var services = Type.GetType("System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer")
?.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, Array.Empty<Type>())
?.Invoke(null) as DbProviderServices;
if (services is not null)
SetProviderServices("System.Data.SqlClient", services);
}
#endregion
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With