Fix DbContext configuration nightmares.

Thanks to julian figuring out IDesignTimeDbContextFactory exists in #6327.

All this DbContext configuration and options setup stuff is insane. Microsoft should be absolutely ashamed for coming up with this load of garbage.
This commit is contained in:
Pieter-Jan Briers
2022-02-03 03:13:34 +01:00
parent 32a1f6ae93
commit 4da56becab
8 changed files with 44 additions and 46 deletions

View File

@@ -0,0 +1,25 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
// ReSharper disable UnusedType.Global
namespace Content.Server.Database;
public sealed class DesignTimeContextFactoryPostgres : IDesignTimeDbContextFactory<PostgresServerDbContext>
{
public PostgresServerDbContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<PostgresServerDbContext>();
optionsBuilder.UseNpgsql(args[0]);
return new PostgresServerDbContext(optionsBuilder.Options);
}
}
public sealed class DesignTimeContextFactorySqlite : IDesignTimeDbContextFactory<SqliteServerDbContext>
{
public SqliteServerDbContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<SqliteServerDbContext>();
optionsBuilder.UseSqlite(args[0]);
return new SqliteServerDbContext(optionsBuilder.Options);
}
}

View File

@@ -11,22 +11,10 @@ namespace Content.Server.Database
{
public abstract class ServerDbContext : DbContext
{
/// <summary>
/// The "dotnet ef" CLI tool uses the parameter-less constructor.
/// When that happens we want to supply the <see cref="DbContextOptions"/> via <see cref="DbContext.OnConfiguring"/>.
/// To use the context within the application, the options need to be passed the constructor instead.
/// </summary>
protected readonly bool InitializedWithOptions;
public ServerDbContext()
protected ServerDbContext(DbContextOptions options) : base(options)
{
}
public ServerDbContext(DbContextOptions<ServerDbContext> options) : base(options)
{
InitializedWithOptions = true;
}
public DbSet<Preference> Preference { get; set; } = null!;
public DbSet<Profile> Profile { get; set; } = null!;
public DbSet<AssignedUserId> AssignedUserId { get; set; } = null!;

View File

@@ -8,21 +8,17 @@ namespace Content.Server.Database
{
public sealed class PostgresServerDbContext : ServerDbContext
{
// This is used by the "dotnet ef" CLI tool.
public PostgresServerDbContext()
{
}
static PostgresServerDbContext()
{
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
}
public PostgresServerDbContext(DbContextOptions<PostgresServerDbContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
if (!InitializedWithOptions)
options.UseNpgsql("dummy connection string");
options.ReplaceService<IRelationalTypeMappingSource, CustomNpgsqlTypeMappingSource>();
((IDbContextOptionsBuilderInfrastructure) options).AddOrUpdateExtension(new SnakeCaseExtension());
@@ -41,10 +37,6 @@ namespace Content.Server.Database
#endif
}
public PostgresServerDbContext(DbContextOptions<ServerDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

View File

@@ -13,15 +13,12 @@ namespace Content.Server.Database
{
public sealed class SqliteServerDbContext : ServerDbContext
{
public SqliteServerDbContext()
public SqliteServerDbContext(DbContextOptions<SqliteServerDbContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
if (!InitializedWithOptions)
options.UseSqlite("dummy connection string");
((IDbContextOptionsBuilderInfrastructure) options).AddOrUpdateExtension(new SnakeCaseExtension());
options.ConfigureWarnings(x =>
@@ -70,10 +67,6 @@ namespace Content.Server.Database
.HasConversion(jsonConverter);
}
public SqliteServerDbContext(DbContextOptions<ServerDbContext> options) : base(options)
{
}
private static string InetToString(IPAddress address, int mask) {
if (address.IsIPv4MappedToIPv6)
{

View File

@@ -180,12 +180,12 @@ namespace Content.Server.Database
switch (engine)
{
case "sqlite":
var options = CreateSqliteOptions();
_db = new ServerDbSqlite(options);
var sqliteOptions = CreateSqliteOptions();
_db = new ServerDbSqlite(sqliteOptions);
break;
case "postgres":
options = CreatePostgresOptions();
_db = new ServerDbPostgres(options);
var pgOptions = CreatePostgresOptions();
_db = new ServerDbPostgres(pgOptions);
break;
default:
throw new InvalidDataException($"Unknown database engine {engine}.");
@@ -394,7 +394,7 @@ namespace Content.Server.Database
return _db.RemoveFromWhitelistAsync(player);
}
private DbContextOptions<ServerDbContext> CreatePostgresOptions()
private DbContextOptions<PostgresServerDbContext> CreatePostgresOptions()
{
var host = _cfg.GetCVar(CCVars.DatabasePgHost);
var port = _cfg.GetCVar(CCVars.DatabasePgPort);
@@ -402,7 +402,7 @@ namespace Content.Server.Database
var user = _cfg.GetCVar(CCVars.DatabasePgUsername);
var pass = _cfg.GetCVar(CCVars.DatabasePgPassword);
var builder = new DbContextOptionsBuilder<ServerDbContext>();
var builder = new DbContextOptionsBuilder<PostgresServerDbContext>();
var connectionString = new NpgsqlConnectionStringBuilder
{
Host = host,
@@ -419,9 +419,9 @@ namespace Content.Server.Database
return builder.Options;
}
private DbContextOptions<ServerDbContext> CreateSqliteOptions()
private DbContextOptions<SqliteServerDbContext> CreateSqliteOptions()
{
var builder = new DbContextOptionsBuilder<ServerDbContext>();
var builder = new DbContextOptionsBuilder<SqliteServerDbContext>();
var configPreferencesDbPath = _cfg.GetCVar(CCVars.DatabaseSqliteDbPath);
var inMemory = _res.UserData.RootDir == null;
@@ -447,7 +447,7 @@ namespace Content.Server.Database
return builder.Options;
}
private void SetupLogging(DbContextOptionsBuilder<ServerDbContext> builder)
private void SetupLogging(DbContextOptionsBuilder builder)
{
builder.UseLoggerFactory(_msLoggerFactory);
}

View File

@@ -13,10 +13,10 @@ namespace Content.Server.Database
{
public sealed class ServerDbPostgres : ServerDbBase
{
private readonly DbContextOptions<ServerDbContext> _options;
private readonly DbContextOptions<PostgresServerDbContext> _options;
private readonly Task _dbReadyTask;
public ServerDbPostgres(DbContextOptions<ServerDbContext> options)
public ServerDbPostgres(DbContextOptions<PostgresServerDbContext> options)
{
_options = options;

View File

@@ -31,7 +31,7 @@ namespace Content.Server.Database
private readonly Task _dbReadyTask;
private readonly SqliteServerDbContext _prefsCtx;
public ServerDbSqlite(DbContextOptions<ServerDbContext> options)
public ServerDbSqlite(DbContextOptions<SqliteServerDbContext> options)
{
_prefsCtx = new SqliteServerDbContext(options);

View File

@@ -67,7 +67,7 @@ namespace Content.Tests.Server.Preferences
private static ServerDbSqlite GetDb()
{
var builder = new DbContextOptionsBuilder<ServerDbContext>();
var builder = new DbContextOptionsBuilder<SqliteServerDbContext>();
var conn = new SqliteConnection("Data Source=:memory:");
conn.Open();
builder.UseSqlite(conn);