-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
I have a project running in different environments with different databases (PostgreSQL / SQL Server). I tried using the same DbContext for both databases but had some problems with migrations since vendor specific code is added (e.g. data types).
I decided to make two distinct contexts, both extending my dbContext.
public abstract class ParcelLogisticsContext : DbContext
{
public DbSet<Parcel> Parcel { get; set; }
public DbSet<HopArrival> HopArrival { get; set; }
public DbSet<Receipient> Receipient { get; set; }
public DbSet<Truck> Truck { get; set; }
public DbSet<Warehouse> Warehouse { get; set; }
public DbSet<ParcelStorage> ParcelStorage { get; set; }
public ParcelLogisticsContext(DbContextOptions options) : base(options)
{
}
}
public class PgSqlParcelLogisticsContext : ParcelLogisticsContext
{
public PgSqlParcelLogisticsContext(DbContextOptions options) : base(options)
{
}
}
public class SqlServerParcelLogisticsContext : ParcelLogisticsContext
{
public SqlServerParcelLogisticsContext(DbContextOptions options) : base(options)
{
}
}
From now on I added migrations using Add-Migration -Context PgSqlParcelLogisticsContext ChangedAwesomeFields
and Add-Migration -Context SqlServerParcelLogisticsContext ChangedAwesomeFields
resulting in different Migrations with vendor specific code in them.
The problem i was facing was with dependency injection. When adding EF like below I was unable to use my abstract base class for dependency injection.
switch (Configuration.GetValue<string>("UsedDatabase"))
{
case "Sql":
services.AddDbContext<SqlServerParcelLogisticsContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ParcelLogisticsContext")));
case "NpgSql":
services.AddEntityFrameworkNpgsql();
services.AddDbContext<PgSqlParcelLogisticsContext>(options => options.UseNpgsql(Configuration.GetConnectionString("ParcelLogisticsContext")));
break;
default:
throw new Exception("InvalidUsedDatabase");
}
Now exceptions are thrown when trying to get a context like so because Dependency Injection could not find a service for type ParcelLogisticsDbContext
:
class Test
{
public Test(ParcelLogisticsDbContext context)
{
}
}
To resolve this issue I added extension methods so I would be able to use AddDbContext
with two type arguments in a similar way e.g. AddScoped
works and I could use it like this:
switch (Configuration.GetValue<string>("UsedDatabase"))
{
case "Sql":
services.AddDbContext<ParcelLogisticsContext, SqlServerParcelLogisticsContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ParcelLogisticsContext")));
break;
case "NpgSql":
services.AddEntityFrameworkNpgsql();
services.AddDbContext<ParcelLogisticsContext, PgSqlParcelLogisticsContext>(options => options.UseNpgsql(Configuration.GetConnectionString("ParcelLogisticsContext")));
break;
default:
throw new Exception("InvalidUsedDatabase");
}
Do you think this is a good solution or do you have any other ideas? I also submitted a Pull Request (#10454) and I am happy for feedback!
Further technical details
EF Core version: 2.0
Database Provider: Microsoft.EntityFrameworkCore.SqlServer, Npgsql.EntityFrameworkCore.PostgreSQL
Operating system: Windows 10 Version 1703
IDE: Visual Studio 2017 15.4.5