2using System.Globalization;
 
    4using System.Reflection;
 
    6using System.Threading.Tasks;
 
    8using Microsoft.EntityFrameworkCore;
 
    9using Microsoft.EntityFrameworkCore.Infrastructure;
 
   10using Microsoft.EntityFrameworkCore.Migrations;
 
   11using Microsoft.Extensions.DependencyInjection;
 
   12using Microsoft.Extensions.Logging;
 
   23#pragma warning disable CA1506  
   29        public DbSet<User> 
Users { 
get; 
set; }
 
   79        public DbSet<Job> 
Jobs { 
get; 
set; }
 
  114        public DbSet<UserGroup> 
Groups { 
get; 
set; }
 
  275            var configureFunction = typeof(TDatabaseContext).GetMethod(
 
  277                BindingFlags.Public | BindingFlags.Static)
 
  278                ?? 
throw new InvalidOperationException($
"Context type {typeof(TDatabaseContext).FullName} missing static {ConfigureMethodName} function!");
 
  279            return (optionsBuilder, config) => configureFunction.Invoke(
null, [optionsBuilder, config]);
 
 
  287            : base(dbContextOptions)
 
 
  310        public Task 
Save(CancellationToken cancellationToken) => SaveChangesAsync(cancellationToken);
 
  313        public Task 
Drop(CancellationToken cancellationToken) => Database.EnsureDeletedAsync(cancellationToken);
 
  316        public async ValueTask<bool> 
Migrate(ILogger<DatabaseContext> logger, CancellationToken cancellationToken)
 
  318            ArgumentNullException.ThrowIfNull(logger);
 
  319            var migrations = await Database.GetAppliedMigrationsAsync(cancellationToken);
 
  320            var wasEmpty = !migrations.Any();
 
  322            if (wasEmpty || (await Database.GetPendingMigrationsAsync(cancellationToken)).Any())
 
  324                logger.LogInformation(
"Migrating database...");
 
  325                await Database.MigrateAsync(cancellationToken);
 
  328                logger.LogDebug(
"No migrations to apply");
 
  330            wasEmpty |= !await 
Users.AsQueryable().AnyAsync(cancellationToken);
 
 
  337            ILogger<DatabaseContext> logger,
 
  338            Version targetVersion,
 
  340            CancellationToken cancellationToken)
 
  342            ArgumentNullException.ThrowIfNull(logger);
 
  343            ArgumentNullException.ThrowIfNull(targetVersion);
 
  344            if (targetVersion < 
new Version(4, 0))
 
  345                throw new ArgumentOutOfRangeException(nameof(targetVersion), targetVersion, 
"Cannot migrate below version 4.0.0!");
 
  347            if (currentDatabaseType == 
DatabaseType.PostgresSql && targetVersion < 
new Version(4, 3, 0))
 
  348                throw new NotSupportedException(
"Cannot migrate below version 4.3.0 with PostgresSql!");
 
  353            if (targetVersion < 
new Version(4, 1, 0))
 
  354                throw new NotSupportedException(
"Cannot migrate below version 4.1.0!");
 
  358            if (targetMigration == 
null)
 
  360                logger.LogDebug(
"No down migration required.");
 
  365            var migrationSubstitution = currentDatabaseType 
switch 
  367                DatabaseType.SqlServer => 
null, 
 
  368                DatabaseType.MySql => 
"MY{0}",
 
  369                DatabaseType.Sqlite => 
"SL{0}",
 
  370                DatabaseType.PostgresSql => 
"PG{0}",
 
  371                _ => 
throw new InvalidOperationException($
"Invalid DatabaseType: {currentDatabaseType}"),
 
  374            if (migrationSubstitution != 
null)
 
  375                targetMigration = String.Format(CultureInfo.InvariantCulture, migrationSubstitution, targetMigration[2..]);
 
  378            var dbServiceProvider = ((IInfrastructure<IServiceProvider>)Database).Instance;
 
  379            var migrator = dbServiceProvider.GetRequiredService<IMigrator>();
 
  381            logger.LogInformation(
"Migrating down to version {targetVersion}. Target: {targetMigration}", targetVersion, targetMigration);
 
  384                await migrator.MigrateAsync(targetMigration, cancellationToken);
 
  388                logger.LogCritical(e, 
"Failed to migrate!");
 
 
  395            ArgumentNullException.ThrowIfNull(modelBuilder);
 
  397            base.OnModelCreating(modelBuilder);
 
  399            var userModel = modelBuilder.Entity<
User>();
 
  400            userModel.HasIndex(x => x.CanonicalName).IsUnique();
 
  401            userModel.HasIndex(x => x.SystemIdentifier).IsUnique();
 
  402            userModel.HasMany(x => x.TestMerges).WithOne(x => x.MergedBy).OnDelete(DeleteBehavior.Restrict);
 
  403            userModel.HasMany(x => x.OAuthConnections).WithOne(x => x.User).OnDelete(DeleteBehavior.Cascade);
 
  404            userModel.HasMany(x => x.OidcConnections).WithOne(x => x.User).OnDelete(DeleteBehavior.Cascade);
 
  406            modelBuilder.Entity<
OAuthConnection>().HasIndex(x => 
new { x.Provider, x.ExternalUserId }).IsUnique();
 
  407            modelBuilder.Entity<
OidcConnection>().HasIndex(x => 
new { x.SchemeKey, x.ExternalUserId }).IsUnique();
 
  409            var groupsModel = modelBuilder.Entity<
UserGroup>();
 
  410            groupsModel.HasIndex(x => x.Name).IsUnique();
 
  411            groupsModel.HasMany(x => x.Users).WithOne(x => x.Group).OnDelete(DeleteBehavior.ClientSetNull);
 
  413            var permissionSetModel = modelBuilder.Entity<
PermissionSet>();
 
  414            permissionSetModel.HasOne(x => x.Group).WithOne(x => x.PermissionSet).OnDelete(DeleteBehavior.Cascade);
 
  415            permissionSetModel.HasOne(x => x.User).WithOne(x => x.PermissionSet).OnDelete(DeleteBehavior.Cascade);
 
  416            permissionSetModel.HasMany(x => x.InstancePermissionSets).WithOne(x => x.PermissionSet).OnDelete(DeleteBehavior.Cascade);
 
  418            modelBuilder.Entity<
InstancePermissionSet>().HasIndex(x => 
new { x.PermissionSetId, x.InstanceId }).IsUnique();
 
  421            revInfo.HasMany(x => x.ActiveTestMerges).WithOne(x => x.RevisionInformation).OnDelete(DeleteBehavior.Cascade);
 
  422            revInfo.HasOne(x => x.PrimaryTestMerge).WithOne(x => x.PrimaryRevisionInformation).OnDelete(DeleteBehavior.Cascade);
 
  423            revInfo.HasIndex(x => 
new { x.InstanceId, x.CommitSha }).IsUnique();
 
  435            modelBuilder.Entity<
TestMerge>().HasMany(x => x.RevisonInformations).WithOne(x => x.TestMerge).OnDelete(DeleteBehavior.ClientNoAction);
 
  437            var compileJob = modelBuilder.Entity<
CompileJob>();
 
  438            compileJob.HasIndex(x => x.DirectoryName);
 
  439            compileJob.HasOne(x => x.Job).WithOne().OnDelete(DeleteBehavior.Cascade);
 
  441            modelBuilder.Entity<
ReattachInformation>().HasOne(x => x.CompileJob).WithMany().OnDelete(DeleteBehavior.Cascade);
 
  443            var chatChannel = modelBuilder.Entity<
ChatChannel>();
 
  444            chatChannel.HasIndex(x => 
new { x.ChatSettingsId, x.IrcChannel }).IsUnique();
 
  445            chatChannel.HasIndex(x => 
new { x.ChatSettingsId, x.DiscordChannelId }).IsUnique();
 
  446            chatChannel.HasOne(x => x.ChatSettings).WithMany(x => x.Channels).HasForeignKey(x => x.ChatSettingsId).OnDelete(DeleteBehavior.Cascade);
 
  448            modelBuilder.Entity<
ChatBot>().HasIndex(x => 
new { x.InstanceId, x.Name }).IsUnique();
 
  450            var instanceModel = modelBuilder.Entity<
Instance>();
 
  451            instanceModel.HasIndex(x => 
new { x.Path, x.SwarmIdentifer }).IsUnique();
 
  452            instanceModel.HasMany(x => x.ChatSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
 
  453            instanceModel.HasOne(x => x.DreamDaemonSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
 
  454            instanceModel.HasOne(x => x.DreamMakerSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
 
  455            instanceModel.HasOne(x => x.RepositorySettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
 
  456            instanceModel.HasMany(x => x.RevisionInformations).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
 
  457            instanceModel.HasMany(x => x.InstancePermissionSets).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
 
  458            instanceModel.HasMany(x => x.Jobs).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
 
 
  496            string? targetMigration = 
null;
 
  498            string BadDatabaseType() => 
throw new ArgumentException($
"Invalid DatabaseType: {currentDatabaseType}", nameof(currentDatabaseType));
 
  501            if (targetVersion < 
new Version(6, 15, 0))
 
  502                targetMigration = currentDatabaseType 
switch 
  508                    _ => BadDatabaseType(),
 
  511            if (targetVersion < 
new Version(6, 12, 0))
 
  512                targetMigration = currentDatabaseType 
switch 
  518                    _ => BadDatabaseType(),
 
  521            if (targetVersion < 
new Version(6, 7, 0))
 
  522                targetMigration = currentDatabaseType 
switch 
  528                    _ => BadDatabaseType(),
 
  531            if (targetVersion < 
new Version(6, 6, 0))
 
  532                targetMigration = currentDatabaseType 
switch 
  538                    _ => BadDatabaseType(),
 
  541            if (targetVersion < 
new Version(6, 5, 0))
 
  542                targetMigration = currentDatabaseType 
switch 
  548                    _ => BadDatabaseType(),
 
  551            if (targetVersion < 
new Version(6, 2, 0))
 
  552                targetMigration = currentDatabaseType 
switch 
  558                    _ => BadDatabaseType(),
 
  561            if (targetVersion < 
new Version(6, 0, 0))
 
  562                targetMigration = currentDatabaseType 
switch 
  568                    _ => BadDatabaseType(),
 
  570            if (targetVersion < 
new Version(5, 17, 0))
 
  571                targetMigration = currentDatabaseType 
switch 
  577                    _ => BadDatabaseType(),
 
  579            if (targetVersion < 
new Version(5, 13, 0))
 
  580                targetMigration = currentDatabaseType 
switch 
  586                    _ => BadDatabaseType(),
 
  588            if (targetVersion < 
new Version(5, 7, 3))
 
  589                targetMigration = currentDatabaseType 
switch 
  595                    _ => BadDatabaseType(),
 
  597            if (targetVersion < 
new Version(5, 7, 0))
 
  598                targetMigration = currentDatabaseType 
switch 
  604                    _ => BadDatabaseType(),
 
  606            if (targetVersion < 
new Version(4, 19, 0))
 
  607                targetMigration = currentDatabaseType 
switch 
  613                    _ => BadDatabaseType(),
 
  615            if (targetVersion < 
new Version(4, 18, 0))
 
  616                targetMigration = currentDatabaseType 
switch 
  622                    _ => BadDatabaseType(),
 
  624            if (targetVersion < 
new Version(4, 14, 0))
 
  625                targetMigration = currentDatabaseType 
switch 
  631                    _ => BadDatabaseType(),
 
  633            if (targetVersion < 
new Version(4, 10, 0))
 
  634                targetMigration = currentDatabaseType 
switch 
  640                    _ => BadDatabaseType(),
 
  642            if (targetVersion < 
new Version(4, 8, 0))
 
  643                targetMigration = currentDatabaseType 
switch 
  649                    _ => BadDatabaseType(),
 
  651            if (targetVersion < 
new Version(4, 7, 0))
 
  652                targetMigration = currentDatabaseType 
switch 
  658                    _ => BadDatabaseType(),
 
  660            if (targetVersion < 
new Version(4, 6, 0))
 
  661                targetMigration = currentDatabaseType 
switch 
  667                    _ => BadDatabaseType(),
 
  669            if (targetVersion < 
new Version(4, 5, 0))
 
  670                targetMigration = currentDatabaseType 
switch 
  676                    _ => BadDatabaseType(),
 
  678            if (targetVersion < 
new Version(4, 4, 0))
 
  679                targetMigration = currentDatabaseType 
switch 
  682                    DatabaseType.PostgresSql => nameof(
PGCreate),
 
  685                    _ => BadDatabaseType(),
 
  688            if (targetVersion < 
new Version(4, 2, 0))
 
  691            return targetMigration;
 
 
 
Backend abstract implementation of IDatabaseContext.
DbSet< ReattachInformation > ReattachInformations
The ReattachInformations in the DatabaseContext.
readonly IDatabaseCollection< UserGroup > groups
Backing field for IDatabaseContext.Groups.
DbSet< Job > Jobs
The Jobs in the DatabaseContext.
DbSet< Instance > Instances
The Instances in the DatabaseContext.
readonly IDatabaseCollection< RevInfoTestMerge > revInfoTestMergesCollection
Backing field for IDatabaseContext.RevInfoTestMerges.
readonly IDatabaseCollection< DreamMakerSettings > dreamMakerSettingsCollection
Backing field for IDatabaseContext.DreamMakerSettings.
virtual DeleteBehavior RevInfoCompileJobDeleteBehavior
The DeleteBehavior for the CompileJob/RevisionInformation foreign key.
readonly IDatabaseCollection< OidcConnection > oidcConnections
Backing field for IDatabaseContext.OidcConnections.
readonly IDatabaseCollection< RepositorySettings > repositorySettingsCollection
Backing field for IDatabaseContext.RepositorySettings.
DbSet< OAuthConnection > OAuthConnections
The OAuthConnections in the DatabaseContext.
readonly IDatabaseCollection< User > usersCollection
Backing field for IDatabaseContext.Users.
readonly IDatabaseCollection< Job > jobsCollection
Backing field for IDatabaseContext.Jobs.
override void OnModelCreating(ModelBuilder modelBuilder)
DbSet< ChatChannel > ChatChannels
The ChatChannels in the DatabaseContext.
DatabaseContext(DbContextOptions dbContextOptions)
Initializes a new instance of the DatabaseContext class.
readonly IDatabaseCollection< DreamDaemonSettings > dreamDaemonSettingsCollection
Backing field for IDatabaseContext.DreamDaemonSettings.
readonly IDatabaseCollection< Instance > instancesCollection
Backing field for IDatabaseContext.Instances.
DbSet< InstancePermissionSet > InstancePermissionSets
The InstancePermissionSets in the DatabaseContext.
DbSet< PermissionSet > PermissionSets
The PermissionSets in the DatabaseContext.
readonly IDatabaseCollection< ChatChannel > chatChannelsCollection
Backing field for IDatabaseContext.ChatChannels.
DbSet< CompileJob > CompileJobs
The CompileJobs in the DatabaseContext.
async ValueTask< bool > Migrate(ILogger< DatabaseContext > logger, CancellationToken cancellationToken)
Creates and migrates the IDatabaseContext.A ValueTask<TResult> resulting in true if the database shou...
readonly IDatabaseCollection< RevisionInformation > revisionInformationsCollection
Backing field for IDatabaseContext.RevisionInformations.
DbSet< TestMerge > TestMerges
The TestMerges in the DatabaseContext.
async ValueTask SchemaDowngradeForServerVersion(ILogger< DatabaseContext > logger, Version targetVersion, DatabaseType currentDatabaseType, CancellationToken cancellationToken)
Attempt to downgrade the schema to the migration used for a given server targetVersion ....
readonly IDatabaseCollection< InstancePermissionSet > instancePermissionSetsCollection
Backing field for IDatabaseContext.InstancePermissionSets.
Task Drop(CancellationToken cancellationToken)
Attempts to delete all tables and drop the database in use.A Task representing the running operation.
readonly IDatabaseCollection< ReattachInformation > reattachInformationsCollection
Backing field for IDatabaseContext.ReattachInformations.
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext.A Task representing the running operation.
readonly IDatabaseCollection< PermissionSet > permissionSets
Backing field for IDatabaseContext.PermissionSets.
readonly IDatabaseCollection< ChatBot > chatBotsCollection
Backing field for IDatabaseContext.ChatBots.
readonly IDatabaseCollection< CompileJob > compileJobsCollection
Backing field for IDatabaseContext.CompileJobs.
string? GetTargetMigration(Version targetVersion, DatabaseType currentDatabaseType)
Gets the name of the migration to run for migrating down to a given targetVersion  for the currentDat...
DbSet< User > Users
The Users in the DatabaseContext.
DbSet< ChatBot > ChatBots
The ChatBots in the DatabaseContext.
DbSet< OidcConnection > OidcConnections
The OidcConnections in the DatabaseContext.
DbSet< RevInfoTestMerge > RevInfoTestMerges
The RevInfoTestMerges in the DatabaseContext.
readonly IDatabaseCollection< OAuthConnection > oAuthConnections
Backing field for IDatabaseContext.OAuthConnections.
readonly IDatabaseCollection< TestMerge > testMergesCollection
Backing field for IDatabaseContext.TestMerges.
static Action< DbContextOptionsBuilder, DatabaseConfiguration > GetConfigureAction< TDatabaseContext >()
Gets the configure action for a given TDatabaseContext .
DbSet< RevisionInformation > RevisionInformations
The RevisionInformations in the DatabaseContext.
DbSet< UserGroup > Groups
The UserGroups in the DatabaseContext.
Adds the AdditionalParameters DD column for MSSQL.
Adds columns for GitHub deployments for MSSQL.
Adds the DreamDaemon LogOutput column for MSSQL.
Adds the DreamMakerSettings DumpOnHeartbeatRestart column for MSSQL.
Adds the MapThreads DreamDaemonSettings column for MSSQL.
Adds the option to start the profiler with DreamDaemon for MSSQL.
Adds the InitialCompileJobId to the ReattachInformations table for MSSQL.
Add the Timestamp column to RevisionInformations for MSSQL.
Adds the swarm identifier column for MSSQL.
Adds the UpdateSubmodules repository setting for MSSQL.
Update models for making the DMAPI optional for MSSQL.
Fix cascading data deletes for Models.Instances on MSSQL.
Removes various defunct columns for MSSQL.
Reduces the index name column size for MSSQL.
Adds the AdditionalParameters DD column for MySQL.
Adds columns for GitHub deployments for MYSQL.
Adds the DreamDaemon LogOutput column for MYSQL.
Adds the DreamMakerSettings DumpOnHeartbeatRestart column for MYSQL.
Adds the MapThreads DreamDaemonSettings column for MYSQL.
Adds the option to start the profiler with DreamDaemon for MYSQL.
Adds the InitialCompileJobId to the ReattachInformations table for MYSQL.
Adds the swarm identifier column for MySQL.
Adds the UpdateSubmodules repository setting for MYSQL.
Update models for making the DMAPI optional for MYSQL.
Fix the CompileJob/RevisionInformation foreign key for MySQL.
Reduces the index name column size for MYSQL.
Adds the AdditionalParameters DD column for PostgresSQL.
Adds columns for GitHub deployments for PostgresSQL.
Adds the DreamDaemon LogOutput column for PostgresSQL.
Adds the DreamMakerSettings DumpOnHeartbeatRestart column for PostgresSQL.
Adds the MapThreads DreamDaemonSettings column for PostgresSQL.
Adds the option to start the profiler with DreamDaemon for PostgresSQL.
Adds the InitialCompileJobId to the ReattachInformations table for PostgresSQL.
Add the Timestamp column to RevisionInformations for PostgresSQL.
Adds the swarm identifier column for PostgresSQL.
Adds the UpdateSubmodules repository setting for PostgresSQL.
Update models for making the DMAPI optional for PostgresSQL.
Create initial schema for PostgresSQL.
Reduces the index name column size for PostgresSQL.
Adds columns for GitHub deployments for SQLite.
Adds columns for GitHub deployments for SQLite.
Adds the DreamDaemon LogOutput column for SQLite.
Adds the DreamMakerSettings DumpOnHeartbeatRestart column for SQLite.
Adds the MapThreads DreamDaemonSettings column for SQLite.
Adds the option to start the profiler with DreamDaemon for SQLite.
Adds the InitialCompileJobId to the ReattachInformations table for SQLite.
Add the Timestamp column to RevisionInformations for SQLite.
Adds the swarm identifier column for SQLite.
Adds the UpdateSubmodules repository setting for SQLite.
Update models for making the DMAPI optional for SQLite.
Rebuild of the schema for SQLite.
Removes various defunct columns for SQLite.
DatabaseContext for Sqlserver.
static void ConfigureWith(DbContextOptionsBuilder options, DatabaseConfiguration databaseConfiguration)
Configure the SqlServerDatabaseContext.
Represents an Api.Models.Instance in the database.
Represents a group of Users.
Represents a database table.
DatabaseType
Type of database to user.