324 ArgumentNullException.ThrowIfNull(modelBuilder);
326 base.OnModelCreating(modelBuilder);
328 var userModel = modelBuilder.Entity<
User>();
329 userModel.HasIndex(x => x.CanonicalName).IsUnique();
330 userModel.HasIndex(x => x.SystemIdentifier).IsUnique();
331 userModel.HasMany(x => x.TestMerges).WithOne(x => x.MergedBy).OnDelete(DeleteBehavior.Restrict);
332 userModel.HasMany(x => x.OAuthConnections).WithOne(x => x.User).OnDelete(DeleteBehavior.Cascade);
334 modelBuilder.Entity<
OAuthConnection>().HasIndex(x =>
new { x.Provider, x.ExternalUserId }).IsUnique();
336 var groupsModel = modelBuilder.Entity<
UserGroup>();
337 groupsModel.HasIndex(x => x.Name).IsUnique();
338 groupsModel.HasMany(x => x.Users).WithOne(x => x.Group).OnDelete(DeleteBehavior.ClientSetNull);
340 var permissionSetModel = modelBuilder.Entity<
PermissionSet>();
341 permissionSetModel.HasOne(x => x.Group).WithOne(x => x.PermissionSet).OnDelete(DeleteBehavior.Cascade);
342 permissionSetModel.HasOne(x => x.User).WithOne(x => x.PermissionSet).OnDelete(DeleteBehavior.Cascade);
343 permissionSetModel.HasMany(x => x.InstancePermissionSets).WithOne(x => x.PermissionSet).OnDelete(DeleteBehavior.Cascade);
345 modelBuilder.Entity<
InstancePermissionSet>().HasIndex(x =>
new { x.PermissionSetId, x.InstanceId }).IsUnique();
348 revInfo.HasMany(x => x.ActiveTestMerges).WithOne(x => x.RevisionInformation).OnDelete(DeleteBehavior.Cascade);
349 revInfo.HasOne(x => x.PrimaryTestMerge).WithOne(x => x.PrimaryRevisionInformation).OnDelete(DeleteBehavior.Cascade);
350 revInfo.HasIndex(x =>
new { x.InstanceId, x.CommitSha }).IsUnique();
362 modelBuilder.Entity<
TestMerge>().HasMany(x => x.RevisonInformations).WithOne(x => x.TestMerge).OnDelete(DeleteBehavior.ClientNoAction);
364 var compileJob = modelBuilder.Entity<
CompileJob>();
365 compileJob.HasIndex(x => x.DirectoryName);
366 compileJob.HasOne(x => x.Job).WithOne().OnDelete(DeleteBehavior.Cascade);
368 modelBuilder.Entity<
ReattachInformation>().HasOne(x => x.CompileJob).WithMany().OnDelete(DeleteBehavior.Cascade);
370 var chatChannel = modelBuilder.Entity<
ChatChannel>();
371 chatChannel.HasIndex(x =>
new { x.ChatSettingsId, x.IrcChannel }).IsUnique();
372 chatChannel.HasIndex(x =>
new { x.ChatSettingsId, x.DiscordChannelId }).IsUnique();
373 chatChannel.HasOne(x => x.ChatSettings).WithMany(x => x.Channels).HasForeignKey(x => x.ChatSettingsId).OnDelete(DeleteBehavior.Cascade);
375 modelBuilder.Entity<
ChatBot>().HasIndex(x =>
new { x.InstanceId, x.Name }).IsUnique();
377 var instanceModel = modelBuilder.Entity<
Instance>();
378 instanceModel.HasIndex(x =>
new { x.Path, x.SwarmIdentifer }).IsUnique();
379 instanceModel.HasMany(x => x.ChatSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
380 instanceModel.HasOne(x => x.DreamDaemonSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
381 instanceModel.HasOne(x => x.DreamMakerSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
382 instanceModel.HasOne(x => x.RepositorySettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
383 instanceModel.HasMany(x => x.RevisionInformations).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
384 instanceModel.HasMany(x => x.InstancePermissionSets).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
385 instanceModel.HasMany(x => x.Jobs).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
416 ILogger<DatabaseContext> logger,
417 Version targetVersion,
419 CancellationToken cancellationToken)
421 ArgumentNullException.ThrowIfNull(logger);
422 ArgumentNullException.ThrowIfNull(targetVersion);
423 if (targetVersion <
new Version(4, 0))
424 throw new ArgumentOutOfRangeException(nameof(targetVersion), targetVersion,
"Cannot migrate below version 4.0.0!");
426 if (currentDatabaseType ==
DatabaseType.PostgresSql && targetVersion <
new Version(4, 3, 0))
427 throw new NotSupportedException(
"Cannot migrate below version 4.3.0 with PostgresSql!");
432 if (targetVersion <
new Version(4, 1, 0))
433 throw new NotSupportedException(
"Cannot migrate below version 4.1.0!");
436 string? targetMigration =
null;
438 string BadDatabaseType() =>
throw new ArgumentException($
"Invalid DatabaseType: {currentDatabaseType}", nameof(currentDatabaseType));
440 if (targetVersion <
new Version(6, 7, 0))
441 targetMigration = currentDatabaseType
switch
447 _ => BadDatabaseType(),
450 if (targetVersion <
new Version(6, 6, 0))
451 targetMigration = currentDatabaseType
switch
457 _ => BadDatabaseType(),
460 if (targetVersion <
new Version(6, 5, 0))
461 targetMigration = currentDatabaseType
switch
467 _ => BadDatabaseType(),
470 if (targetVersion <
new Version(6, 2, 0))
471 targetMigration = currentDatabaseType
switch
477 _ => BadDatabaseType(),
480 if (targetVersion <
new Version(6, 0, 0))
481 targetMigration = currentDatabaseType
switch
487 _ => BadDatabaseType(),
489 if (targetVersion <
new Version(5, 17, 0))
490 targetMigration = currentDatabaseType
switch
496 _ => BadDatabaseType(),
498 if (targetVersion <
new Version(5, 13, 0))
499 targetMigration = currentDatabaseType
switch
505 _ => BadDatabaseType(),
507 if (targetVersion <
new Version(5, 7, 3))
508 targetMigration = currentDatabaseType
switch
514 _ => BadDatabaseType(),
516 if (targetVersion <
new Version(5, 7, 0))
517 targetMigration = currentDatabaseType
switch
523 _ => BadDatabaseType(),
525 if (targetVersion <
new Version(4, 19, 0))
526 targetMigration = currentDatabaseType
switch
532 _ => BadDatabaseType(),
534 if (targetVersion <
new Version(4, 18, 0))
535 targetMigration = currentDatabaseType
switch
541 _ => BadDatabaseType(),
543 if (targetVersion <
new Version(4, 14, 0))
544 targetMigration = currentDatabaseType
switch
550 _ => BadDatabaseType(),
552 if (targetVersion <
new Version(4, 10, 0))
553 targetMigration = currentDatabaseType
switch
559 _ => BadDatabaseType(),
561 if (targetVersion <
new Version(4, 8, 0))
562 targetMigration = currentDatabaseType
switch
568 _ => BadDatabaseType(),
570 if (targetVersion <
new Version(4, 7, 0))
571 targetMigration = currentDatabaseType
switch
577 _ => BadDatabaseType(),
579 if (targetVersion <
new Version(4, 6, 0))
580 targetMigration = currentDatabaseType
switch
586 _ => BadDatabaseType(),
588 if (targetVersion <
new Version(4, 5, 0))
589 targetMigration = currentDatabaseType
switch
595 _ => BadDatabaseType(),
597 if (targetVersion <
new Version(4, 4, 0))
598 targetMigration = currentDatabaseType
switch
601 DatabaseType.PostgresSql => nameof(
PGCreate),
604 _ => BadDatabaseType(),
606 if (targetVersion <
new Version(4, 2, 0))
609 if (targetMigration ==
null)
611 logger.LogDebug(
"No down migration required.");
616 var migrationSubstitution = currentDatabaseType
switch
618 DatabaseType.SqlServer =>
null,
619 DatabaseType.MySql =>
"MY{0}",
620 DatabaseType.Sqlite =>
"SL{0}",
621 DatabaseType.PostgresSql =>
"PG{0}",
622 _ =>
throw new InvalidOperationException($
"Invalid DatabaseType: {currentDatabaseType}"),
625 if (migrationSubstitution !=
null)
626 targetMigration = String.Format(CultureInfo.InvariantCulture, migrationSubstitution, targetMigration[2..]);
629 var dbServiceProvider = ((IInfrastructure<IServiceProvider>)Database).Instance;
630 var migrator = dbServiceProvider.GetRequiredService<IMigrator>();
632 logger.LogInformation(
"Migrating down to version {targetVersion}. Target: {targetMigration}", targetVersion, targetMigration);
635 await migrator.MigrateAsync(targetMigration, cancellationToken);
639 logger.LogCritical(e,
"Failed to migrate!");