From 95d957241d6ee4bcc9a6199bb1f8d0a1cb9d8059 Mon Sep 17 00:00:00 2001 From: Roger Date: Tue, 12 May 2026 16:12:38 -0700 Subject: [PATCH 1/4] Add database indexes for perf improvements --- Data/DataModel/PuzzleUser.cs | 1 + ...0512223806_DbIndexImprovements.Designer.cs | 2236 +++++++++++++++++ .../20260512223806_DbIndexImprovements.cs | 169 ++ .../PuzzleServerContextModelSnapshot.cs | 34 +- Data/PuzzleServerContext.cs | 11 +- 5 files changed, 2442 insertions(+), 9 deletions(-) create mode 100644 Data/Migrations/20260512223806_DbIndexImprovements.Designer.cs create mode 100644 Data/Migrations/20260512223806_DbIndexImprovements.cs diff --git a/Data/DataModel/PuzzleUser.cs b/Data/DataModel/PuzzleUser.cs index 07cb9881..43a9a9b2 100644 --- a/Data/DataModel/PuzzleUser.cs +++ b/Data/DataModel/PuzzleUser.cs @@ -23,6 +23,7 @@ public class PuzzleUser /// [ForeignKey("AspNetUsers.Id")] [Required] + [MaxLength(450)] public string IdentityUserId { get; set; } [PersonalData] diff --git a/Data/Migrations/20260512223806_DbIndexImprovements.Designer.cs b/Data/Migrations/20260512223806_DbIndexImprovements.Designer.cs new file mode 100644 index 00000000..cfd75772 --- /dev/null +++ b/Data/Migrations/20260512223806_DbIndexImprovements.Designer.cs @@ -0,0 +1,2236 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using ServerCore.DataModel; + +#nullable disable + +namespace Data.Migrations +{ + [DbContext(typeof(PuzzleServerContext))] + [Migration("20260512223806_DbIndexImprovements")] + partial class DbIndexImprovements + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Proxies:ChangeTracking", false) + .HasAnnotation("Proxies:CheckEquality", false) + .HasAnnotation("Proxies:LazyLoading", true) + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("ServerCore.DataModel.Annotation", b => + { + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.Property("Key") + .HasColumnType("int"); + + b.Property("Contents") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Version") + .HasColumnType("int"); + + b.HasKey("PuzzleID", "TeamID", "Key"); + + b.HasIndex("TeamID"); + + b.ToTable("Annotations"); + }); + + modelBuilder.Entity("ServerCore.DataModel.ContentFile", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("FileType") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("UrlString") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("ID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("EventID", "FileType") + .IsUnique(); + + SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("EventID", "FileType"), new[] { "ShortName", "UrlString", "PuzzleID" }); + + b.HasIndex("EventID", "ShortName") + .IsUnique(); + + b.ToTable("ContentFiles"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Event", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AllowFeedback") + .HasColumnType("bit"); + + b.Property("AllowsRemotePlayers") + .HasColumnType("bit") + .HasColumnName("AllowsRemote"); + + b.Property("AllowsRemoteTeams") + .HasColumnType("bit"); + + b.Property("Announcement") + .HasColumnType("nvarchar(max)"); + + b.Property("AnswerSubmissionEnd") + .HasColumnType("datetime2"); + + b.Property("AnswersAvailableBegin") + .HasColumnType("datetime2"); + + b.Property("ContactEmail") + .HasColumnType("nvarchar(max)"); + + b.Property("Copyright") + .HasColumnType("nvarchar(max)"); + + b.Property("DefaultCostForHelpThread") + .HasColumnType("int"); + + b.Property("DefaultLunch") + .HasColumnType("nvarchar(max)"); + + b.Property("EphemeralHacks") + .HasColumnType("nvarchar(max)"); + + b.Property("EventBegin") + .HasColumnType("datetime2"); + + b.Property("EventHasTeamSwag") + .HasColumnType("bit"); + + b.Property("EventPassword") + .HasColumnType("nvarchar(max)"); + + b.Property("FAQContent") + .HasColumnType("nvarchar(max)"); + + b.Property("FastestSyncIntervalMs") + .HasColumnType("int"); + + b.Property("HasIndividualLunch") + .HasColumnType("bit"); + + b.Property("HasPlayerClasses") + .HasColumnType("bit"); + + b.Property("HasSwag") + .HasColumnType("bit") + .HasColumnName("EventHasSwag"); + + b.Property("HasTShirts") + .HasColumnType("bit"); + + b.Property("HideHints") + .HasColumnType("bit"); + + b.Property("HideSolveCounts") + .HasColumnType("bit"); + + b.Property("HideStandings") + .HasColumnType("bit"); + + b.Property("HomeContent") + .HasColumnType("nvarchar(max)"); + + b.Property("HomePartial") + .HasColumnType("nvarchar(max)"); + + b.Property("IsAlphaTestingEvent") + .HasColumnType("bit"); + + b.Property("IsInternEvent") + .HasColumnType("bit"); + + b.Property("IsRemote") + .HasColumnType("bit"); + + b.Property("LockChangesToRemoteStatus") + .HasColumnType("bit"); + + b.Property("LockoutDurationMultiplier") + .HasColumnType("float"); + + b.Property("LockoutIncorrectGuessLimit") + .HasColumnType("int"); + + b.Property("LockoutIncorrectGuessPeriod") + .HasColumnType("float"); + + b.Property("LunchDescription") + .HasColumnType("nvarchar(max)"); + + b.Property("LunchOptions") + .HasColumnType("nvarchar(max)"); + + b.Property("LunchOptionsPerLunch") + .HasColumnType("int"); + + b.Property("LunchReportDate") + .HasColumnType("datetime2"); + + b.Property("MaxExternalsPerTeam") + .HasColumnType("int"); + + b.Property("MaxNumberOfLocalTeams") + .HasColumnType("int"); + + b.Property("MaxNumberOfRemoteTeams") + .HasColumnType("int"); + + b.Property("MaxNumberOfTeams") + .HasColumnType("int"); + + b.Property("MaxSubmissionCount") + .HasColumnType("bigint"); + + b.Property("MaxTeamSize") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PlayerClassName") + .HasColumnType("nvarchar(max)"); + + b.Property("PlayersPerLunch") + .HasColumnType("int"); + + b.Property("PuzzleListCustomHeaderUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("PuzzleSyncEnabled") + .HasColumnType("bit"); + + b.Property("RulesContent") + .HasColumnType("nvarchar(max)"); + + b.Property("ShouldSendHelpThreadMailToGameControl") + .HasColumnType("bit"); + + b.Property("ShouldShowHelpMessageOnlyToAuthor") + .HasColumnType("bit"); + + b.Property("SinglePlayerPuzzleTitle") + .HasColumnType("nvarchar(max)"); + + b.Property("TeamAnnouncement") + .HasColumnType("nvarchar(max)"); + + b.Property("TeamDeleteEnd") + .HasColumnType("datetime2"); + + b.Property("TeamMembershipChangeEnd") + .HasColumnType("datetime2"); + + b.Property("TeamMiscDataChangeEnd") + .HasColumnType("datetime2"); + + b.Property("TeamNameChangeEnd") + .HasColumnType("datetime2"); + + b.Property("TeamRegistrationBegin") + .HasColumnType("datetime2"); + + b.Property("TeamRegistrationEnd") + .HasColumnType("datetime2"); + + b.Property("TermForGroup") + .HasColumnType("nvarchar(max)"); + + b.Property("UrlString") + .HasColumnType("nvarchar(450)"); + + b.HasKey("ID"); + + b.HasIndex("UrlString") + .IsUnique() + .HasFilter("[UrlString] IS NOT NULL"); + + b.ToTable("Events"); + }); + + modelBuilder.Entity("ServerCore.DataModel.EventAdmins", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AdminID") + .HasColumnType("int"); + + b.Property("EventID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("EventID"); + + b.HasIndex("AdminID", "EventID") + .IsUnique(); + + b.ToTable("EventAdmins"); + }); + + modelBuilder.Entity("ServerCore.DataModel.EventAuthors", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AuthorID") + .HasColumnType("int"); + + b.Property("EventID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("EventID"); + + b.HasIndex("AuthorID", "EventID") + .IsUnique(); + + b.ToTable("EventAuthors"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Feedback", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("Difficulty") + .HasColumnType("int"); + + b.Property("Fun") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("SubmissionTime") + .HasColumnType("datetime2"); + + b.Property("SubmitterID") + .HasColumnType("int"); + + b.Property("WrittenFeedback") + .HasColumnType("nvarchar(max)"); + + b.HasKey("ID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("SubmitterID"); + + b.ToTable("Feedback"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Hint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Cost") + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PuzzleID"); + + b.ToTable("Hints"); + }); + + modelBuilder.Entity("ServerCore.DataModel.HintStatePerTeam", b => + { + b.Property("TeamID") + .HasColumnType("int"); + + b.Property("HintID") + .HasColumnType("int"); + + b.Property("UnlockTime") + .HasColumnType("datetime2"); + + b.HasKey("TeamID", "HintID"); + + b.HasIndex("HintID"); + + b.ToTable("HintStatePerTeam"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Invitation", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("EmailAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Expiration") + .HasColumnType("datetime2"); + + b.Property("InvitationCode") + .HasColumnType("uniqueidentifier"); + + b.Property("InvitationType") + .HasColumnType("nvarchar(max)"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("TeamID"); + + b.ToTable("Invitations"); + }); + + modelBuilder.Entity("ServerCore.DataModel.LiveEvent", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AssociatedPuzzleId") + .HasColumnType("int"); + + b.Property("ClosingReminderOffset") + .HasColumnType("time"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("EventEndTimeUtc") + .HasColumnType("datetime2"); + + b.Property("EventIsScheduled") + .HasColumnType("bit"); + + b.Property("EventStartTimeUtc") + .HasColumnType("datetime2"); + + b.Property("FirstReminderOffset") + .HasColumnType("time"); + + b.Property("LastNotifiedAllTeamsUtc") + .HasColumnType("datetime2"); + + b.Property("LastReminderOffset") + .HasColumnType("time"); + + b.Property("Location") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NumberOfInstances") + .HasColumnType("int"); + + b.Property("OpeningReminderOffset") + .HasColumnType("time"); + + b.Property("TeamsPerSlot") + .HasColumnType("int"); + + b.Property("TimePerSlot") + .HasColumnType("time"); + + b.HasKey("ID"); + + b.HasIndex("AssociatedPuzzleId"); + + b.ToTable("LiveEvents"); + }); + + modelBuilder.Entity("ServerCore.DataModel.LiveEventSchedule", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("LastNotifiedUtc") + .HasColumnType("datetime2"); + + b.Property("LiveEventId") + .HasColumnType("int"); + + b.Property("StartTimeUtc") + .HasColumnType("datetime2"); + + b.Property("TeamId") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("LiveEventId"); + + b.HasIndex("TeamId"); + + b.ToTable("LiveEventsSchedule"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Message", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("ClaimerID") + .HasColumnType("int"); + + b.Property("CreatedDateTimeInUtc") + .HasColumnType("datetime2"); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("IsFromGameControl") + .HasColumnType("bit"); + + b.Property("ModifiedDateTimeInUtc") + .HasColumnType("datetime2"); + + b.Property("PlayerID") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("SenderID") + .HasColumnType("int"); + + b.Property("Subject") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.Property("Text") + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.Property("ThreadId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("ID"); + + b.HasIndex("ClaimerID"); + + b.HasIndex("EventID"); + + b.HasIndex("PlayerID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("SenderID"); + + b.HasIndex("TeamID"); + + b.HasIndex("ThreadId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Piece", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("Contents") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ProgressLevel") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("ProgressLevel", "PuzzleID"); + + SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("ProgressLevel", "PuzzleID"), new[] { "ID", "Contents" }); + + b.ToTable("Pieces"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PlayerClass", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("UniqueName") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.HasKey("ID"); + + b.HasIndex("EventID"); + + b.ToTable("PlayerClasses"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PlayerInEvent", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("EventId") + .HasColumnType("int"); + + b.Property("HintCoinCount") + .HasColumnType("int"); + + b.Property("HintCoinsUsed") + .HasColumnType("int"); + + b.Property("IsRemote") + .HasColumnType("bit"); + + b.Property("Lunch") + .HasColumnType("nvarchar(max)"); + + b.Property("LunchModifications") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("PlayerId") + .HasColumnType("int"); + + b.Property("ShirtSize") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.HasKey("ID"); + + b.HasIndex("EventId"); + + b.HasIndex("PlayerId", "EventId"); + + b.ToTable("Swag"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Prerequisites", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("PrerequisiteID") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("PrerequisiteID"); + + b.HasIndex("PuzzleID"); + + b.ToTable("Prerequisites"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Puzzle", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AlphaTestsNeeded") + .HasColumnType("int"); + + b.Property("Availability") + .HasColumnType("int"); + + b.Property("CostForHelpThread") + .HasColumnType("int"); + + b.Property("CustomAuthorText") + .HasColumnType("nvarchar(max)"); + + b.Property("CustomCSSFile") + .HasColumnType("nvarchar(max)"); + + b.Property("CustomSolutionURL") + .HasColumnType("nvarchar(max)"); + + b.Property("CustomURL") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Errata") + .HasColumnType("nvarchar(max)"); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("Group") + .HasColumnType("nvarchar(max)"); + + b.Property("HasDataConfirmation") + .HasColumnType("bit"); + + b.Property("HintCoinsForSolve") + .HasColumnType("int"); + + b.Property("HintsAreCumulative") + .HasColumnType("bit"); + + b.Property("IsCheatCode") + .HasColumnType("bit"); + + b.Property("IsFinalPuzzle") + .HasColumnType("bit"); + + b.Property("IsForSinglePlayer") + .HasColumnType("bit"); + + b.Property("IsFreeform") + .HasColumnType("bit"); + + b.Property("IsGloballyVisiblePrerequisite") + .HasColumnType("bit"); + + b.Property("IsMetaPuzzle") + .HasColumnType("bit"); + + b.Property("IsPuzzle") + .HasColumnType("bit"); + + b.Property("MaxAnnotationKey") + .HasColumnType("int"); + + b.Property("MinInGroupCount") + .HasColumnType("int"); + + b.Property("MinPrerequisiteCount") + .HasColumnType("int"); + + b.Property("MinutesOfEventLockout") + .HasColumnType("int"); + + b.Property("MinutesToAutomaticallySolve") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrderInGroup") + .HasColumnType("int"); + + b.Property("PieceMetaTagFilter") + .HasColumnType("nvarchar(max)"); + + b.Property("PieceMetaUsage") + .HasColumnType("int"); + + b.Property("PieceTag") + .HasColumnType("nvarchar(max)"); + + b.Property("PieceWeight") + .HasColumnType("int"); + + b.Property("PrerequisiteWeight") + .HasColumnType("int"); + + b.Property("PuzzleVersion") + .HasColumnType("int"); + + b.Property("ShowHelpThreadsToAllGameControl") + .HasColumnType("bit"); + + b.Property("SolveValue") + .HasColumnType("int"); + + b.Property("SupportEmailAlias") + .HasColumnType("nvarchar(max)"); + + b.Property("Token") + .HasColumnType("nvarchar(max)"); + + b.HasKey("ID"); + + b.HasIndex("EventID"); + + b.HasIndex("MinutesOfEventLockout", "Availability", "ID"); + + b.HasIndex("MinutesToAutomaticallySolve", "Availability", "ID"); + + b.ToTable("Puzzles"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PuzzleAuthors", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AuthorID") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("SupportOnly") + .HasColumnType("bit"); + + b.HasKey("ID"); + + b.HasIndex("AuthorID"); + + b.HasIndex("PuzzleID"); + + b.ToTable("PuzzleAuthors"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PuzzleStatePerTeam", b => + { + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.Property("IsEmailOnlyMode") + .HasColumnType("bit"); + + b.Property("IsHelpThreadUnlockedByCoins") + .HasColumnType("bit"); + + b.Property("LockoutExpiryTime") + .HasColumnType("datetime2"); + + b.Property("Notes") + .HasColumnType("nvarchar(max)"); + + b.Property("Printed") + .HasColumnType("bit"); + + b.Property("SolvedTime") + .HasColumnType("datetime2"); + + b.Property("UnlockedTime") + .HasColumnType("datetime2"); + + b.Property("WrongSubmissionCountBuffer") + .HasColumnType("bigint"); + + b.HasKey("PuzzleID", "TeamID"); + + b.HasIndex("TeamID"); + + b.HasIndex("TeamID", "SolvedTime"); + + b.ToTable("PuzzleStatePerTeam"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PuzzleUser", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("Email") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("EmployeeAlias") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("IdentityUserId") + .IsRequired() + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("IsGlobalAdmin") + .HasColumnType("bit"); + + b.Property("MayBeAdminOrAuthor") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("PhoneNumber") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("TShirtSize") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("VisibleToOthers") + .HasColumnType("bit"); + + b.HasKey("ID"); + + b.HasIndex("IdentityUserId"); + + b.ToTable("PuzzleUsers"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Response", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("IsSolution") + .HasColumnType("bit"); + + b.Property("Note") + .HasColumnType("nvarchar(max)"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("ResponseText") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SubmittedText") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("ID"); + + b.HasIndex("PuzzleID"); + + b.ToTable("Responses"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Room", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("Building") + .HasColumnType("nvarchar(450)"); + + b.Property("Capacity") + .HasColumnType("int"); + + b.Property("CurrentlyOnline") + .HasColumnType("bit"); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("Group") + .HasColumnType("nvarchar(max)"); + + b.Property("Number") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("TeamID"); + + b.HasIndex("EventID", "Building", "Number") + .IsUnique() + .HasFilter("[Building] IS NOT NULL"); + + b.ToTable("Rooms"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleHintStatePerPlayer", b => + { + b.Property("PlayerID") + .HasColumnType("int"); + + b.Property("HintID") + .HasColumnType("int"); + + b.Property("UnlockTime") + .HasColumnType("datetime2"); + + b.HasKey("PlayerID", "HintID"); + + b.HasIndex("HintID"); + + b.ToTable("SinglePlayerPuzzleHintStatePerPlayer"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleStatePerPlayer", b => + { + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("PlayerID") + .HasColumnType("int"); + + b.Property("IsEmailOnlyMode") + .HasColumnType("bit"); + + b.Property("IsHelpThreadUnlockedByCoins") + .HasColumnType("bit"); + + b.Property("LockoutExpiryTime") + .HasColumnType("datetime2"); + + b.Property("Notes") + .HasColumnType("nvarchar(max)"); + + b.Property("Printed") + .HasColumnType("bit"); + + b.Property("SolvedTime") + .HasColumnType("datetime2"); + + b.Property("UnlockedTime") + .HasColumnType("datetime2"); + + b.Property("WrongSubmissionCountBuffer") + .HasColumnType("bigint"); + + b.HasKey("PuzzleID", "PlayerID"); + + b.HasIndex("PlayerID"); + + b.HasIndex("PlayerID", "SolvedTime"); + + b.ToTable("SinglePlayerPuzzleStatePerPlayer"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleSubmission", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AllowFreeformSharing") + .HasColumnType("bit"); + + b.Property("FreeformAccepted") + .HasColumnType("bit"); + + b.Property("FreeformFavorited") + .HasColumnType("bit"); + + b.Property("FreeformJudgeID") + .HasColumnType("int"); + + b.Property("FreeformResponse") + .HasColumnType("nvarchar(max)"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("ResponseID") + .HasColumnType("int"); + + b.Property("SubmissionText") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SubmitterDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("SubmitterID") + .HasColumnType("int"); + + b.Property("TimeSubmitted") + .HasColumnType("datetime2"); + + b.HasKey("ID"); + + b.HasIndex("FreeformJudgeID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("ResponseID"); + + b.HasIndex("SubmitterID", "PuzzleID", "SubmissionText") + .IsUnique(); + + b.ToTable("SinglePlayerPuzzleSubmissions"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleUnlockState", b => + { + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("UnlockedTime") + .HasColumnType("datetime2"); + + b.HasKey("PuzzleID"); + + b.ToTable("SinglePlayerPuzzleUnlockStates"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Submission", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AllowFreeformSharing") + .HasColumnType("bit"); + + b.Property("FreeformAccepted") + .HasColumnType("bit"); + + b.Property("FreeformFavorited") + .HasColumnType("bit"); + + b.Property("FreeformJudgeID") + .HasColumnType("int"); + + b.Property("FreeformResponse") + .HasColumnType("nvarchar(max)"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("ResponseID") + .HasColumnType("int"); + + b.Property("SubmissionText") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SubmitterDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("SubmitterID") + .HasColumnType("int"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.Property("TeamID1") + .HasColumnType("int"); + + b.Property("TimeSubmitted") + .HasColumnType("datetime2"); + + b.HasKey("ID"); + + b.HasIndex("FreeformJudgeID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("ResponseID"); + + b.HasIndex("SubmitterID"); + + b.HasIndex("TeamID1"); + + b.HasIndex("TeamID", "PuzzleID", "SubmissionText") + .IsUnique(); + + b.ToTable("Submissions"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Team", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AutoApproveTeammates") + .HasColumnType("bit"); + + b.Property("AutoTeamType") + .HasColumnType("int"); + + b.Property("Bio") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("CustomRoom") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("HintCoinCount") + .HasColumnType("int"); + + b.Property("HintCoinsUsed") + .HasColumnType("int"); + + b.Property("IsDisqualified") + .HasColumnType("bit"); + + b.Property("IsLookingForTeammates") + .HasColumnType("bit"); + + b.Property("IsRemoteTeam") + .HasColumnType("bit"); + + b.Property("MergedTeams") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Password") + .HasColumnType("nvarchar(max)"); + + b.Property("PrimaryContactEmail") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("PrimaryPhoneNumber") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("SecondaryPhoneNumber") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("ShowTeamAnnouncement") + .HasColumnType("bit"); + + b.HasKey("ID"); + + b.HasIndex("EventID"); + + b.ToTable("Teams"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamApplication", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("PlayerID") + .HasColumnType("int"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("PlayerID"); + + b.HasIndex("TeamID"); + + b.ToTable("TeamApplications"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamLunch", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("Lunch") + .HasColumnType("nvarchar(max)"); + + b.Property("LunchModifications") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("TeamId") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("TeamId"); + + b.ToTable("TeamLunch"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamMembers", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("ClassID") + .HasColumnType("int"); + + b.Property("Team.ID") + .HasColumnType("int"); + + b.Property("TemporaryClassID") + .HasColumnType("int"); + + b.Property("User.ID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("ClassID"); + + b.HasIndex("ID"); + + b.HasIndex("Team.ID"); + + b.HasIndex("TemporaryClassID"); + + b.HasIndex("User.ID"); + + b.ToTable("TeamMembers"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ServerCore.DataModel.Annotation", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Puzzle"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.ContentFile", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany("Contents") + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Event"); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.EventAdmins", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Admin") + .WithMany() + .HasForeignKey("AdminID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Admin"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("ServerCore.DataModel.EventAuthors", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Author") + .WithMany() + .HasForeignKey("AuthorID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Feedback", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Submitter") + .WithMany() + .HasForeignKey("SubmitterID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Puzzle"); + + b.Navigation("Submitter"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Hint", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.HintStatePerTeam", b => + { + b.HasOne("ServerCore.DataModel.Hint", "Hint") + .WithMany() + .HasForeignKey("HintID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Hint"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Invitation", b => + { + b.HasOne("ServerCore.DataModel.Team", null) + .WithMany("Invitations") + .HasForeignKey("TeamID"); + }); + + modelBuilder.Entity("ServerCore.DataModel.LiveEvent", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "AssociatedPuzzle") + .WithMany() + .HasForeignKey("AssociatedPuzzleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AssociatedPuzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.LiveEventSchedule", b => + { + b.HasOne("ServerCore.DataModel.LiveEvent", "LiveEvent") + .WithMany() + .HasForeignKey("LiveEventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LiveEvent"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Message", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerID") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") + .WithMany() + .HasForeignKey("PlayerID") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Sender") + .WithMany() + .HasForeignKey("SenderID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Claimer"); + + b.Navigation("Event"); + + b.Navigation("Player"); + + b.Navigation("Puzzle"); + + b.Navigation("Sender"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Piece", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PlayerClass", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PlayerInEvent", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") + .WithMany() + .HasForeignKey("PlayerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Event"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Prerequisites", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Prerequisite") + .WithMany() + .HasForeignKey("PrerequisiteID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prerequisite"); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Puzzle", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PuzzleAuthors", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Author") + .WithMany() + .HasForeignKey("AuthorID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PuzzleStatePerTeam", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Puzzle"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Response", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Room", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID"); + + b.Navigation("Event"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleHintStatePerPlayer", b => + { + b.HasOne("ServerCore.DataModel.Hint", "Hint") + .WithMany() + .HasForeignKey("HintID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") + .WithMany() + .HasForeignKey("PlayerID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Hint"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleStatePerPlayer", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") + .WithMany() + .HasForeignKey("PlayerID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Player"); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleSubmission", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "FreeformJudge") + .WithMany() + .HasForeignKey("FreeformJudgeID"); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany("SinglePlayerPuzzleSubmissions") + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Response", "Response") + .WithMany() + .HasForeignKey("ResponseID"); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Submitter") + .WithMany() + .HasForeignKey("SubmitterID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("FreeformJudge"); + + b.Navigation("Puzzle"); + + b.Navigation("Response"); + + b.Navigation("Submitter"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleUnlockState", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Submission", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "FreeformJudge") + .WithMany() + .HasForeignKey("FreeformJudgeID"); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany("Submissions") + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Response", "Response") + .WithMany() + .HasForeignKey("ResponseID"); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Submitter") + .WithMany() + .HasForeignKey("SubmitterID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", null) + .WithMany("Submissions") + .HasForeignKey("TeamID1"); + + b.Navigation("FreeformJudge"); + + b.Navigation("Puzzle"); + + b.Navigation("Response"); + + b.Navigation("Submitter"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Team", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamApplication", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") + .WithMany() + .HasForeignKey("PlayerID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Player"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamLunch", b => + { + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamMembers", b => + { + b.HasOne("ServerCore.DataModel.PlayerClass", "Class") + .WithMany() + .HasForeignKey("ClassID"); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("Team.ID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.PlayerClass", "TemporaryClass") + .WithMany() + .HasForeignKey("TemporaryClassID"); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Member") + .WithMany() + .HasForeignKey("User.ID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Class"); + + b.Navigation("Member"); + + b.Navigation("Team"); + + b.Navigation("TemporaryClass"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Puzzle", b => + { + b.Navigation("Contents"); + + b.Navigation("SinglePlayerPuzzleSubmissions"); + + b.Navigation("Submissions"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Team", b => + { + b.Navigation("Invitations"); + + b.Navigation("Submissions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Data/Migrations/20260512223806_DbIndexImprovements.cs b/Data/Migrations/20260512223806_DbIndexImprovements.cs new file mode 100644 index 00000000..7dc0007e --- /dev/null +++ b/Data/Migrations/20260512223806_DbIndexImprovements.cs @@ -0,0 +1,169 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Data.Migrations +{ + /// + public partial class DbIndexImprovements : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_Swag_PlayerId", + table: "Swag"); + + migrationBuilder.DropIndex( + name: "IX_Pieces_ProgressLevel", + table: "Pieces"); + + migrationBuilder.DropIndex( + name: "IX_EventAuthors_AuthorID", + table: "EventAuthors"); + + migrationBuilder.DropIndex( + name: "IX_EventAdmins_AdminID", + table: "EventAdmins"); + + migrationBuilder.AlterColumn( + name: "IdentityUserId", + table: "PuzzleUsers", + type: "nvarchar(450)", + maxLength: 450, + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AddColumn( + name: "PuzzleListCustomHeaderUrl", + table: "Events", + type: "nvarchar(max)", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_TeamMembers_UserID_TeamID", + table: "TeamMembers", + columns: new[] { "User.ID", "Team.ID" }) + .Annotation("SqlServer:Include", new[] { "ID", "ClassID", "TemporaryClassID" }); + + migrationBuilder.CreateIndex( + name: "IX_Swag_PlayerId_EventId", + table: "Swag", + columns: new[] { "PlayerId", "EventId" }); + + migrationBuilder.CreateIndex( + name: "IX_PuzzleUsers_IdentityUserId", + table: "PuzzleUsers", + column: "IdentityUserId"); + + migrationBuilder.CreateIndex( + name: "IX_Puzzles_MinutesOfEventLockout_Availability_ID", + table: "Puzzles", + columns: new[] { "MinutesOfEventLockout", "Availability", "ID" }); + + migrationBuilder.CreateIndex( + name: "IX_Puzzles_MinutesToAutomaticallySolve_Availability_ID", + table: "Puzzles", + columns: new[] { "MinutesToAutomaticallySolve", "Availability", "ID" }); + + migrationBuilder.CreateIndex( + name: "IX_Pieces_ProgressLevel_PuzzleID", + table: "Pieces", + columns: new[] { "ProgressLevel", "PuzzleID" }) + .Annotation("SqlServer:Include", new[] { "ID", "Contents" }); + + migrationBuilder.CreateIndex( + name: "IX_EventAuthors_AuthorID_EventID", + table: "EventAuthors", + columns: new[] { "AuthorID", "EventID" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_EventAdmins_AdminID_EventID", + table: "EventAdmins", + columns: new[] { "AdminID", "EventID" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ContentFiles_EventID_FileType", + table: "ContentFiles", + columns: new[] { "EventID", "FileType" }, + unique: true) + .Annotation("SqlServer:Include", new[] { "ShortName", "UrlString", "PuzzleID" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_TeamMembers_UserID_TeamID", + table: "TeamMembers"); + + migrationBuilder.DropIndex( + name: "IX_Swag_PlayerId_EventId", + table: "Swag"); + + migrationBuilder.DropIndex( + name: "IX_PuzzleUsers_IdentityUserId", + table: "PuzzleUsers"); + + migrationBuilder.DropIndex( + name: "IX_Puzzles_MinutesOfEventLockout_Availability_ID", + table: "Puzzles"); + + migrationBuilder.DropIndex( + name: "IX_Puzzles_MinutesToAutomaticallySolve_Availability_ID", + table: "Puzzles"); + + migrationBuilder.DropIndex( + name: "IX_Pieces_ProgressLevel_PuzzleID", + table: "Pieces"); + + migrationBuilder.DropIndex( + name: "IX_EventAuthors_AuthorID_EventID", + table: "EventAuthors"); + + migrationBuilder.DropIndex( + name: "IX_EventAdmins_AdminID_EventID", + table: "EventAdmins"); + + migrationBuilder.DropIndex( + name: "IX_ContentFiles_EventID_FileType", + table: "ContentFiles"); + + migrationBuilder.DropColumn( + name: "PuzzleListCustomHeaderUrl", + table: "Events"); + + migrationBuilder.AlterColumn( + name: "IdentityUserId", + table: "PuzzleUsers", + type: "nvarchar(max)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)", + oldMaxLength: 450); + + migrationBuilder.CreateIndex( + name: "IX_Swag_PlayerId", + table: "Swag", + column: "PlayerId"); + + migrationBuilder.CreateIndex( + name: "IX_Pieces_ProgressLevel", + table: "Pieces", + column: "ProgressLevel"); + + migrationBuilder.CreateIndex( + name: "IX_EventAuthors_AuthorID", + table: "EventAuthors", + column: "AuthorID"); + + migrationBuilder.CreateIndex( + name: "IX_EventAdmins_AdminID", + table: "EventAdmins", + column: "AdminID"); + } + } +} diff --git a/Data/Migrations/PuzzleServerContextModelSnapshot.cs b/Data/Migrations/PuzzleServerContextModelSnapshot.cs index a33d239b..90ba741d 100644 --- a/Data/Migrations/PuzzleServerContextModelSnapshot.cs +++ b/Data/Migrations/PuzzleServerContextModelSnapshot.cs @@ -285,6 +285,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); + b.HasIndex("EventID", "FileType") + .IsUnique(); + + SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("EventID", "FileType"), new[] { "ShortName", "UrlString", "PuzzleID" }); + b.HasIndex("EventID", "ShortName") .IsUnique(); @@ -507,10 +512,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); - b.HasIndex("AdminID"); - b.HasIndex("EventID"); + b.HasIndex("AdminID", "EventID") + .IsUnique(); + b.ToTable("EventAdmins"); }); @@ -530,10 +536,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); - b.HasIndex("AuthorID"); - b.HasIndex("EventID"); + b.HasIndex("AuthorID", "EventID") + .IsUnique(); + b.ToTable("EventAuthors"); }); @@ -828,10 +835,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); - b.HasIndex("ProgressLevel"); - b.HasIndex("PuzzleID"); + b.HasIndex("ProgressLevel", "PuzzleID"); + + SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("ProgressLevel", "PuzzleID"), new[] { "ID", "Contents" }); + b.ToTable("Pieces"); }); @@ -904,7 +913,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventId"); - b.HasIndex("PlayerId"); + b.HasIndex("PlayerId", "EventId"); b.ToTable("Swag"); }); @@ -1059,6 +1068,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventID"); + b.HasIndex("MinutesOfEventLockout", "Availability", "ID"); + + b.HasIndex("MinutesToAutomaticallySolve", "Availability", "ID"); + b.ToTable("Puzzles"); }); @@ -1148,7 +1161,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("IdentityUserId") .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); b.Property("IsGlobalAdmin") .HasColumnType("bit"); @@ -1174,6 +1188,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); + b.HasIndex("IdentityUserId"); + b.ToTable("PuzzleUsers"); }); @@ -1593,6 +1609,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ClassID"); + b.HasIndex("ID"); + b.HasIndex("Team.ID"); b.HasIndex("TemporaryClassID"); diff --git a/Data/PuzzleServerContext.cs b/Data/PuzzleServerContext.cs index efa15861..e15d1ffc 100644 --- a/Data/PuzzleServerContext.cs +++ b/Data/PuzzleServerContext.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; namespace ServerCore.DataModel @@ -67,12 +68,17 @@ public static void UpdateDatabase(IApplicationBuilder app) protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().HasIndex(contentFile => new { contentFile.EventID, contentFile.ShortName }).IsUnique(); + modelBuilder.Entity().HasIndex(contentFile => new { contentFile.EventID, contentFile.FileType}).IncludeProperties(contentFile => new { contentFile.ShortName, contentFile.UrlString, contentFile.PuzzleID}).IsUnique(); modelBuilder.Entity().HasKey(state => new { state.PuzzleID, state.TeamID }); modelBuilder.Entity().HasKey(state => new { state.TeamID, state.HintID }); modelBuilder.Entity().HasKey(state => new { state.PlayerID, state.HintID }); modelBuilder.Entity().HasIndex(eventObj => new { eventObj.UrlString }).IsUnique(); + modelBuilder.Entity().HasIndex(admin => new { admin.AdminID, admin.EventID}).IsUnique(); + modelBuilder.Entity().HasIndex(author => new { author.AuthorID, author.EventID }).IsUnique(); modelBuilder.Entity().HasKey(state => new { state.PuzzleID, state.TeamID, state.Key }); - modelBuilder.Entity().HasIndex(piece => new { piece.ProgressLevel }); + modelBuilder.Entity().HasIndex(piece => new { piece.ProgressLevel, piece.PuzzleID }).IncludeProperties(piece => new { piece.ID, piece.Contents }); + modelBuilder.Entity().HasIndex(puzzle=> new { puzzle.MinutesOfEventLockout, puzzle.Availability, puzzle.ID}); + modelBuilder.Entity().HasIndex(puzzle => new { puzzle.MinutesToAutomaticallySolve, puzzle.Availability, puzzle.ID }); modelBuilder.Entity().HasIndex(submission => new { submission.TeamID, submission.PuzzleID, submission.SubmissionText }).IsUnique(); modelBuilder.Entity().HasIndex(submission => new { submission.SubmitterID, submission.PuzzleID, submission.SubmissionText }).IsUnique(); modelBuilder.Entity().HasIndex(pspt => new { pspt.TeamID }); @@ -82,6 +88,9 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasIndex(pspt => new { pspt.PlayerID, pspt.SolvedTime }); modelBuilder.Entity().HasKey(state => new { state.PuzzleID }); modelBuilder.Entity().HasIndex(room => new { room.EventID, room.Building, room.Number }).IsUnique(); + modelBuilder.Entity().HasIndex(pie => new { pie.PlayerId, pie.EventId}); + modelBuilder.Entity().HasIndex(pu => new { pu.IdentityUserId}); + modelBuilder.Entity().HasIndex(tm => new { tm.ID }); //EF can't parse this for nested types, so this is a placeholder to manually edit the generated model to INDEX Team.ID, User.ID, INCLUDE Class.ID, ID, TemporaryClassID modelBuilder.Entity().HasIndex(message => message.ThreadId); modelBuilder.Entity().HasIndex(message => message.EventID); modelBuilder.Entity().HasIndex(message => message.PuzzleID); From ec07ede5618840ab3483ac3a9e4fada4a0cbd2d5 Mon Sep 17 00:00:00 2001 From: Roger Date: Wed, 20 May 2026 21:48:36 -0700 Subject: [PATCH 2/4] bugfixes to index improvements --- Data/DataModel/TeamMembers.cs | 26 +- ...0512223806_DbIndexImprovements.Designer.cs | 2236 ----------------- .../20260512223806_DbIndexImprovements.cs | 169 -- .../PuzzleServerContextModelSnapshot.cs | 103 +- Data/PuzzleServerContext.cs | 4 +- 5 files changed, 65 insertions(+), 2473 deletions(-) delete mode 100644 Data/Migrations/20260512223806_DbIndexImprovements.Designer.cs delete mode 100644 Data/Migrations/20260512223806_DbIndexImprovements.cs diff --git a/Data/DataModel/TeamMembers.cs b/Data/DataModel/TeamMembers.cs index b8e1b744..c62039f1 100644 --- a/Data/DataModel/TeamMembers.cs +++ b/Data/DataModel/TeamMembers.cs @@ -9,25 +9,47 @@ public class TeamMembers public int ID { get; set; } /// - /// Foreign Key - Team table + /// Populates with Team.ID /// [ForeignKey("Team.ID")] + [Column("Team.ID")] + public int TeamID { get; set; } + + /// + /// Foreign Key - Team table + /// [Required] public virtual Team Team { get; set; } /// - /// Foreign Key - User table + /// Populates with User.ID /// [ForeignKey("User.ID")] + [Column("User.ID")] + public int MemberID { get; set; } + + /// + /// Foreign Key - User table + /// [Required] public virtual PuzzleUser Member { get; set; } + /// + /// Populates with Class.ID + /// + public int? ClassID { get; set; } + /// /// The class or category that the player falls into (classes are defined per event if used). /// This is for player categories unique to an event (e.g. character class for an RPG event or region if relevant for an international event) /// public virtual PlayerClass Class { get; set; } + /// + /// Populates with TemporaryClass.ID + /// + public int? TemporaryClassID { get; set; } + /// /// If the player or event allows an override class that applies to the player temporarily /// This can be set and unset by the player on the TeamDetails page diff --git a/Data/Migrations/20260512223806_DbIndexImprovements.Designer.cs b/Data/Migrations/20260512223806_DbIndexImprovements.Designer.cs deleted file mode 100644 index cfd75772..00000000 --- a/Data/Migrations/20260512223806_DbIndexImprovements.Designer.cs +++ /dev/null @@ -1,2236 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using ServerCore.DataModel; - -#nullable disable - -namespace Data.Migrations -{ - [DbContext(typeof(PuzzleServerContext))] - [Migration("20260512223806_DbIndexImprovements")] - partial class DbIndexImprovements - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.5") - .HasAnnotation("Proxies:ChangeTracking", false) - .HasAnnotation("Proxies:CheckEquality", false) - .HasAnnotation("Proxies:LazyLoading", true) - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasMaxLength(450) - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasMaxLength(450) - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("RoleId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("nvarchar(450)"); - - b.Property("LoginProvider") - .HasMaxLength(450) - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasMaxLength(450) - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("ServerCore.DataModel.Annotation", b => - { - b.Property("PuzzleID") - .HasColumnType("int"); - - b.Property("TeamID") - .HasColumnType("int"); - - b.Property("Key") - .HasColumnType("int"); - - b.Property("Contents") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("nvarchar(255)"); - - b.Property("Timestamp") - .HasColumnType("datetime2"); - - b.Property("Version") - .HasColumnType("int"); - - b.HasKey("PuzzleID", "TeamID", "Key"); - - b.HasIndex("TeamID"); - - b.ToTable("Annotations"); - }); - - modelBuilder.Entity("ServerCore.DataModel.ContentFile", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("EventID") - .HasColumnType("int"); - - b.Property("FileType") - .HasColumnType("int"); - - b.Property("PuzzleID") - .HasColumnType("int"); - - b.Property("ShortName") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("UrlString") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("ID"); - - b.HasIndex("PuzzleID"); - - b.HasIndex("EventID", "FileType") - .IsUnique(); - - SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("EventID", "FileType"), new[] { "ShortName", "UrlString", "PuzzleID" }); - - b.HasIndex("EventID", "ShortName") - .IsUnique(); - - b.ToTable("ContentFiles"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Event", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("AllowFeedback") - .HasColumnType("bit"); - - b.Property("AllowsRemotePlayers") - .HasColumnType("bit") - .HasColumnName("AllowsRemote"); - - b.Property("AllowsRemoteTeams") - .HasColumnType("bit"); - - b.Property("Announcement") - .HasColumnType("nvarchar(max)"); - - b.Property("AnswerSubmissionEnd") - .HasColumnType("datetime2"); - - b.Property("AnswersAvailableBegin") - .HasColumnType("datetime2"); - - b.Property("ContactEmail") - .HasColumnType("nvarchar(max)"); - - b.Property("Copyright") - .HasColumnType("nvarchar(max)"); - - b.Property("DefaultCostForHelpThread") - .HasColumnType("int"); - - b.Property("DefaultLunch") - .HasColumnType("nvarchar(max)"); - - b.Property("EphemeralHacks") - .HasColumnType("nvarchar(max)"); - - b.Property("EventBegin") - .HasColumnType("datetime2"); - - b.Property("EventHasTeamSwag") - .HasColumnType("bit"); - - b.Property("EventPassword") - .HasColumnType("nvarchar(max)"); - - b.Property("FAQContent") - .HasColumnType("nvarchar(max)"); - - b.Property("FastestSyncIntervalMs") - .HasColumnType("int"); - - b.Property("HasIndividualLunch") - .HasColumnType("bit"); - - b.Property("HasPlayerClasses") - .HasColumnType("bit"); - - b.Property("HasSwag") - .HasColumnType("bit") - .HasColumnName("EventHasSwag"); - - b.Property("HasTShirts") - .HasColumnType("bit"); - - b.Property("HideHints") - .HasColumnType("bit"); - - b.Property("HideSolveCounts") - .HasColumnType("bit"); - - b.Property("HideStandings") - .HasColumnType("bit"); - - b.Property("HomeContent") - .HasColumnType("nvarchar(max)"); - - b.Property("HomePartial") - .HasColumnType("nvarchar(max)"); - - b.Property("IsAlphaTestingEvent") - .HasColumnType("bit"); - - b.Property("IsInternEvent") - .HasColumnType("bit"); - - b.Property("IsRemote") - .HasColumnType("bit"); - - b.Property("LockChangesToRemoteStatus") - .HasColumnType("bit"); - - b.Property("LockoutDurationMultiplier") - .HasColumnType("float"); - - b.Property("LockoutIncorrectGuessLimit") - .HasColumnType("int"); - - b.Property("LockoutIncorrectGuessPeriod") - .HasColumnType("float"); - - b.Property("LunchDescription") - .HasColumnType("nvarchar(max)"); - - b.Property("LunchOptions") - .HasColumnType("nvarchar(max)"); - - b.Property("LunchOptionsPerLunch") - .HasColumnType("int"); - - b.Property("LunchReportDate") - .HasColumnType("datetime2"); - - b.Property("MaxExternalsPerTeam") - .HasColumnType("int"); - - b.Property("MaxNumberOfLocalTeams") - .HasColumnType("int"); - - b.Property("MaxNumberOfRemoteTeams") - .HasColumnType("int"); - - b.Property("MaxNumberOfTeams") - .HasColumnType("int"); - - b.Property("MaxSubmissionCount") - .HasColumnType("bigint"); - - b.Property("MaxTeamSize") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PlayerClassName") - .HasColumnType("nvarchar(max)"); - - b.Property("PlayersPerLunch") - .HasColumnType("int"); - - b.Property("PuzzleListCustomHeaderUrl") - .HasColumnType("nvarchar(max)"); - - b.Property("PuzzleSyncEnabled") - .HasColumnType("bit"); - - b.Property("RulesContent") - .HasColumnType("nvarchar(max)"); - - b.Property("ShouldSendHelpThreadMailToGameControl") - .HasColumnType("bit"); - - b.Property("ShouldShowHelpMessageOnlyToAuthor") - .HasColumnType("bit"); - - b.Property("SinglePlayerPuzzleTitle") - .HasColumnType("nvarchar(max)"); - - b.Property("TeamAnnouncement") - .HasColumnType("nvarchar(max)"); - - b.Property("TeamDeleteEnd") - .HasColumnType("datetime2"); - - b.Property("TeamMembershipChangeEnd") - .HasColumnType("datetime2"); - - b.Property("TeamMiscDataChangeEnd") - .HasColumnType("datetime2"); - - b.Property("TeamNameChangeEnd") - .HasColumnType("datetime2"); - - b.Property("TeamRegistrationBegin") - .HasColumnType("datetime2"); - - b.Property("TeamRegistrationEnd") - .HasColumnType("datetime2"); - - b.Property("TermForGroup") - .HasColumnType("nvarchar(max)"); - - b.Property("UrlString") - .HasColumnType("nvarchar(450)"); - - b.HasKey("ID"); - - b.HasIndex("UrlString") - .IsUnique() - .HasFilter("[UrlString] IS NOT NULL"); - - b.ToTable("Events"); - }); - - modelBuilder.Entity("ServerCore.DataModel.EventAdmins", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("AdminID") - .HasColumnType("int"); - - b.Property("EventID") - .HasColumnType("int"); - - b.HasKey("ID"); - - b.HasIndex("EventID"); - - b.HasIndex("AdminID", "EventID") - .IsUnique(); - - b.ToTable("EventAdmins"); - }); - - modelBuilder.Entity("ServerCore.DataModel.EventAuthors", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("AuthorID") - .HasColumnType("int"); - - b.Property("EventID") - .HasColumnType("int"); - - b.HasKey("ID"); - - b.HasIndex("EventID"); - - b.HasIndex("AuthorID", "EventID") - .IsUnique(); - - b.ToTable("EventAuthors"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Feedback", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("Difficulty") - .HasColumnType("int"); - - b.Property("Fun") - .HasColumnType("int"); - - b.Property("PuzzleID") - .HasColumnType("int"); - - b.Property("SubmissionTime") - .HasColumnType("datetime2"); - - b.Property("SubmitterID") - .HasColumnType("int"); - - b.Property("WrittenFeedback") - .HasColumnType("nvarchar(max)"); - - b.HasKey("ID"); - - b.HasIndex("PuzzleID"); - - b.HasIndex("SubmitterID"); - - b.ToTable("Feedback"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Hint", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Content") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Cost") - .HasColumnType("int"); - - b.Property("Description") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DisplayOrder") - .HasColumnType("int"); - - b.Property("PuzzleID") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("PuzzleID"); - - b.ToTable("Hints"); - }); - - modelBuilder.Entity("ServerCore.DataModel.HintStatePerTeam", b => - { - b.Property("TeamID") - .HasColumnType("int"); - - b.Property("HintID") - .HasColumnType("int"); - - b.Property("UnlockTime") - .HasColumnType("datetime2"); - - b.HasKey("TeamID", "HintID"); - - b.HasIndex("HintID"); - - b.ToTable("HintStatePerTeam"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Invitation", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("EmailAddress") - .HasColumnType("nvarchar(max)"); - - b.Property("Expiration") - .HasColumnType("datetime2"); - - b.Property("InvitationCode") - .HasColumnType("uniqueidentifier"); - - b.Property("InvitationType") - .HasColumnType("nvarchar(max)"); - - b.Property("TeamID") - .HasColumnType("int"); - - b.HasKey("ID"); - - b.HasIndex("TeamID"); - - b.ToTable("Invitations"); - }); - - modelBuilder.Entity("ServerCore.DataModel.LiveEvent", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("AssociatedPuzzleId") - .HasColumnType("int"); - - b.Property("ClosingReminderOffset") - .HasColumnType("time"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("EventEndTimeUtc") - .HasColumnType("datetime2"); - - b.Property("EventIsScheduled") - .HasColumnType("bit"); - - b.Property("EventStartTimeUtc") - .HasColumnType("datetime2"); - - b.Property("FirstReminderOffset") - .HasColumnType("time"); - - b.Property("LastNotifiedAllTeamsUtc") - .HasColumnType("datetime2"); - - b.Property("LastReminderOffset") - .HasColumnType("time"); - - b.Property("Location") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("NumberOfInstances") - .HasColumnType("int"); - - b.Property("OpeningReminderOffset") - .HasColumnType("time"); - - b.Property("TeamsPerSlot") - .HasColumnType("int"); - - b.Property("TimePerSlot") - .HasColumnType("time"); - - b.HasKey("ID"); - - b.HasIndex("AssociatedPuzzleId"); - - b.ToTable("LiveEvents"); - }); - - modelBuilder.Entity("ServerCore.DataModel.LiveEventSchedule", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("LastNotifiedUtc") - .HasColumnType("datetime2"); - - b.Property("LiveEventId") - .HasColumnType("int"); - - b.Property("StartTimeUtc") - .HasColumnType("datetime2"); - - b.Property("TeamId") - .HasColumnType("int"); - - b.HasKey("ID"); - - b.HasIndex("LiveEventId"); - - b.HasIndex("TeamId"); - - b.ToTable("LiveEventsSchedule"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Message", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("ClaimerID") - .HasColumnType("int"); - - b.Property("CreatedDateTimeInUtc") - .HasColumnType("datetime2"); - - b.Property("EventID") - .HasColumnType("int"); - - b.Property("IsFromGameControl") - .HasColumnType("bit"); - - b.Property("ModifiedDateTimeInUtc") - .HasColumnType("datetime2"); - - b.Property("PlayerID") - .HasColumnType("int"); - - b.Property("PuzzleID") - .HasColumnType("int"); - - b.Property("SenderID") - .HasColumnType("int"); - - b.Property("Subject") - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); - - b.Property("TeamID") - .HasColumnType("int"); - - b.Property("Text") - .HasMaxLength(4000) - .HasColumnType("nvarchar(4000)"); - - b.Property("ThreadId") - .HasColumnType("nvarchar(450)"); - - b.HasKey("ID"); - - b.HasIndex("ClaimerID"); - - b.HasIndex("EventID"); - - b.HasIndex("PlayerID"); - - b.HasIndex("PuzzleID"); - - b.HasIndex("SenderID"); - - b.HasIndex("TeamID"); - - b.HasIndex("ThreadId"); - - b.ToTable("Messages"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Piece", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("Contents") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("ProgressLevel") - .HasColumnType("int"); - - b.Property("PuzzleID") - .HasColumnType("int"); - - b.HasKey("ID"); - - b.HasIndex("PuzzleID"); - - b.HasIndex("ProgressLevel", "PuzzleID"); - - SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("ProgressLevel", "PuzzleID"), new[] { "ID", "Contents" }); - - b.ToTable("Pieces"); - }); - - modelBuilder.Entity("ServerCore.DataModel.PlayerClass", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("EventID") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Order") - .HasColumnType("int"); - - b.Property("UniqueName") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("nvarchar(20)"); - - b.HasKey("ID"); - - b.HasIndex("EventID"); - - b.ToTable("PlayerClasses"); - }); - - modelBuilder.Entity("ServerCore.DataModel.PlayerInEvent", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("EventId") - .HasColumnType("int"); - - b.Property("HintCoinCount") - .HasColumnType("int"); - - b.Property("HintCoinsUsed") - .HasColumnType("int"); - - b.Property("IsRemote") - .HasColumnType("bit"); - - b.Property("Lunch") - .HasColumnType("nvarchar(max)"); - - b.Property("LunchModifications") - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); - - b.Property("PlayerId") - .HasColumnType("int"); - - b.Property("ShirtSize") - .HasMaxLength(20) - .HasColumnType("nvarchar(20)"); - - b.HasKey("ID"); - - b.HasIndex("EventId"); - - b.HasIndex("PlayerId", "EventId"); - - b.ToTable("Swag"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Prerequisites", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("PrerequisiteID") - .HasColumnType("int"); - - b.Property("PuzzleID") - .HasColumnType("int"); - - b.HasKey("ID"); - - b.HasIndex("PrerequisiteID"); - - b.HasIndex("PuzzleID"); - - b.ToTable("Prerequisites"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Puzzle", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("AlphaTestsNeeded") - .HasColumnType("int"); - - b.Property("Availability") - .HasColumnType("int"); - - b.Property("CostForHelpThread") - .HasColumnType("int"); - - b.Property("CustomAuthorText") - .HasColumnType("nvarchar(max)"); - - b.Property("CustomCSSFile") - .HasColumnType("nvarchar(max)"); - - b.Property("CustomSolutionURL") - .HasColumnType("nvarchar(max)"); - - b.Property("CustomURL") - .HasColumnType("nvarchar(max)"); - - b.Property("Description") - .HasColumnType("nvarchar(max)"); - - b.Property("Errata") - .HasColumnType("nvarchar(max)"); - - b.Property("EventID") - .HasColumnType("int"); - - b.Property("Group") - .HasColumnType("nvarchar(max)"); - - b.Property("HasDataConfirmation") - .HasColumnType("bit"); - - b.Property("HintCoinsForSolve") - .HasColumnType("int"); - - b.Property("HintsAreCumulative") - .HasColumnType("bit"); - - b.Property("IsCheatCode") - .HasColumnType("bit"); - - b.Property("IsFinalPuzzle") - .HasColumnType("bit"); - - b.Property("IsForSinglePlayer") - .HasColumnType("bit"); - - b.Property("IsFreeform") - .HasColumnType("bit"); - - b.Property("IsGloballyVisiblePrerequisite") - .HasColumnType("bit"); - - b.Property("IsMetaPuzzle") - .HasColumnType("bit"); - - b.Property("IsPuzzle") - .HasColumnType("bit"); - - b.Property("MaxAnnotationKey") - .HasColumnType("int"); - - b.Property("MinInGroupCount") - .HasColumnType("int"); - - b.Property("MinPrerequisiteCount") - .HasColumnType("int"); - - b.Property("MinutesOfEventLockout") - .HasColumnType("int"); - - b.Property("MinutesToAutomaticallySolve") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrderInGroup") - .HasColumnType("int"); - - b.Property("PieceMetaTagFilter") - .HasColumnType("nvarchar(max)"); - - b.Property("PieceMetaUsage") - .HasColumnType("int"); - - b.Property("PieceTag") - .HasColumnType("nvarchar(max)"); - - b.Property("PieceWeight") - .HasColumnType("int"); - - b.Property("PrerequisiteWeight") - .HasColumnType("int"); - - b.Property("PuzzleVersion") - .HasColumnType("int"); - - b.Property("ShowHelpThreadsToAllGameControl") - .HasColumnType("bit"); - - b.Property("SolveValue") - .HasColumnType("int"); - - b.Property("SupportEmailAlias") - .HasColumnType("nvarchar(max)"); - - b.Property("Token") - .HasColumnType("nvarchar(max)"); - - b.HasKey("ID"); - - b.HasIndex("EventID"); - - b.HasIndex("MinutesOfEventLockout", "Availability", "ID"); - - b.HasIndex("MinutesToAutomaticallySolve", "Availability", "ID"); - - b.ToTable("Puzzles"); - }); - - modelBuilder.Entity("ServerCore.DataModel.PuzzleAuthors", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("AuthorID") - .HasColumnType("int"); - - b.Property("PuzzleID") - .HasColumnType("int"); - - b.Property("SupportOnly") - .HasColumnType("bit"); - - b.HasKey("ID"); - - b.HasIndex("AuthorID"); - - b.HasIndex("PuzzleID"); - - b.ToTable("PuzzleAuthors"); - }); - - modelBuilder.Entity("ServerCore.DataModel.PuzzleStatePerTeam", b => - { - b.Property("PuzzleID") - .HasColumnType("int"); - - b.Property("TeamID") - .HasColumnType("int"); - - b.Property("IsEmailOnlyMode") - .HasColumnType("bit"); - - b.Property("IsHelpThreadUnlockedByCoins") - .HasColumnType("bit"); - - b.Property("LockoutExpiryTime") - .HasColumnType("datetime2"); - - b.Property("Notes") - .HasColumnType("nvarchar(max)"); - - b.Property("Printed") - .HasColumnType("bit"); - - b.Property("SolvedTime") - .HasColumnType("datetime2"); - - b.Property("UnlockedTime") - .HasColumnType("datetime2"); - - b.Property("WrongSubmissionCountBuffer") - .HasColumnType("bigint"); - - b.HasKey("PuzzleID", "TeamID"); - - b.HasIndex("TeamID"); - - b.HasIndex("TeamID", "SolvedTime"); - - b.ToTable("PuzzleStatePerTeam"); - }); - - modelBuilder.Entity("ServerCore.DataModel.PuzzleUser", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("Email") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("EmployeeAlias") - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("IdentityUserId") - .IsRequired() - .HasMaxLength(450) - .HasColumnType("nvarchar(450)"); - - b.Property("IsGlobalAdmin") - .HasColumnType("bit"); - - b.Property("MayBeAdminOrAuthor") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("nvarchar(50)"); - - b.Property("PhoneNumber") - .HasMaxLength(20) - .HasColumnType("nvarchar(20)"); - - b.Property("TShirtSize") - .HasMaxLength(20) - .HasColumnType("nvarchar(20)"); - - b.Property("VisibleToOthers") - .HasColumnType("bit"); - - b.HasKey("ID"); - - b.HasIndex("IdentityUserId"); - - b.ToTable("PuzzleUsers"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Response", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("IsSolution") - .HasColumnType("bit"); - - b.Property("Note") - .HasColumnType("nvarchar(max)"); - - b.Property("PuzzleID") - .HasColumnType("int"); - - b.Property("ResponseText") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("SubmittedText") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.HasKey("ID"); - - b.HasIndex("PuzzleID"); - - b.ToTable("Responses"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Room", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("Building") - .HasColumnType("nvarchar(450)"); - - b.Property("Capacity") - .HasColumnType("int"); - - b.Property("CurrentlyOnline") - .HasColumnType("bit"); - - b.Property("EventID") - .HasColumnType("int"); - - b.Property("Group") - .HasColumnType("nvarchar(max)"); - - b.Property("Number") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("TeamID") - .HasColumnType("int"); - - b.HasKey("ID"); - - b.HasIndex("TeamID"); - - b.HasIndex("EventID", "Building", "Number") - .IsUnique() - .HasFilter("[Building] IS NOT NULL"); - - b.ToTable("Rooms"); - }); - - modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleHintStatePerPlayer", b => - { - b.Property("PlayerID") - .HasColumnType("int"); - - b.Property("HintID") - .HasColumnType("int"); - - b.Property("UnlockTime") - .HasColumnType("datetime2"); - - b.HasKey("PlayerID", "HintID"); - - b.HasIndex("HintID"); - - b.ToTable("SinglePlayerPuzzleHintStatePerPlayer"); - }); - - modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleStatePerPlayer", b => - { - b.Property("PuzzleID") - .HasColumnType("int"); - - b.Property("PlayerID") - .HasColumnType("int"); - - b.Property("IsEmailOnlyMode") - .HasColumnType("bit"); - - b.Property("IsHelpThreadUnlockedByCoins") - .HasColumnType("bit"); - - b.Property("LockoutExpiryTime") - .HasColumnType("datetime2"); - - b.Property("Notes") - .HasColumnType("nvarchar(max)"); - - b.Property("Printed") - .HasColumnType("bit"); - - b.Property("SolvedTime") - .HasColumnType("datetime2"); - - b.Property("UnlockedTime") - .HasColumnType("datetime2"); - - b.Property("WrongSubmissionCountBuffer") - .HasColumnType("bigint"); - - b.HasKey("PuzzleID", "PlayerID"); - - b.HasIndex("PlayerID"); - - b.HasIndex("PlayerID", "SolvedTime"); - - b.ToTable("SinglePlayerPuzzleStatePerPlayer"); - }); - - modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleSubmission", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("AllowFreeformSharing") - .HasColumnType("bit"); - - b.Property("FreeformAccepted") - .HasColumnType("bit"); - - b.Property("FreeformFavorited") - .HasColumnType("bit"); - - b.Property("FreeformJudgeID") - .HasColumnType("int"); - - b.Property("FreeformResponse") - .HasColumnType("nvarchar(max)"); - - b.Property("PuzzleID") - .HasColumnType("int"); - - b.Property("ResponseID") - .HasColumnType("int"); - - b.Property("SubmissionText") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("SubmitterDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("SubmitterID") - .HasColumnType("int"); - - b.Property("TimeSubmitted") - .HasColumnType("datetime2"); - - b.HasKey("ID"); - - b.HasIndex("FreeformJudgeID"); - - b.HasIndex("PuzzleID"); - - b.HasIndex("ResponseID"); - - b.HasIndex("SubmitterID", "PuzzleID", "SubmissionText") - .IsUnique(); - - b.ToTable("SinglePlayerPuzzleSubmissions"); - }); - - modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleUnlockState", b => - { - b.Property("PuzzleID") - .HasColumnType("int"); - - b.Property("UnlockedTime") - .HasColumnType("datetime2"); - - b.HasKey("PuzzleID"); - - b.ToTable("SinglePlayerPuzzleUnlockStates"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Submission", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("AllowFreeformSharing") - .HasColumnType("bit"); - - b.Property("FreeformAccepted") - .HasColumnType("bit"); - - b.Property("FreeformFavorited") - .HasColumnType("bit"); - - b.Property("FreeformJudgeID") - .HasColumnType("int"); - - b.Property("FreeformResponse") - .HasColumnType("nvarchar(max)"); - - b.Property("PuzzleID") - .HasColumnType("int"); - - b.Property("ResponseID") - .HasColumnType("int"); - - b.Property("SubmissionText") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("nvarchar(1000)"); - - b.Property("SubmitterDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("SubmitterID") - .HasColumnType("int"); - - b.Property("TeamID") - .HasColumnType("int"); - - b.Property("TeamID1") - .HasColumnType("int"); - - b.Property("TimeSubmitted") - .HasColumnType("datetime2"); - - b.HasKey("ID"); - - b.HasIndex("FreeformJudgeID"); - - b.HasIndex("PuzzleID"); - - b.HasIndex("ResponseID"); - - b.HasIndex("SubmitterID"); - - b.HasIndex("TeamID1"); - - b.HasIndex("TeamID", "PuzzleID", "SubmissionText") - .IsUnique(); - - b.ToTable("Submissions"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Team", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("AutoApproveTeammates") - .HasColumnType("bit"); - - b.Property("AutoTeamType") - .HasColumnType("int"); - - b.Property("Bio") - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); - - b.Property("CustomRoom") - .HasMaxLength(200) - .HasColumnType("nvarchar(200)"); - - b.Property("EventID") - .HasColumnType("int"); - - b.Property("HintCoinCount") - .HasColumnType("int"); - - b.Property("HintCoinsUsed") - .HasColumnType("int"); - - b.Property("IsDisqualified") - .HasColumnType("bit"); - - b.Property("IsLookingForTeammates") - .HasColumnType("bit"); - - b.Property("IsRemoteTeam") - .HasColumnType("bit"); - - b.Property("MergedTeams") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("nvarchar(100)"); - - b.Property("Password") - .HasColumnType("nvarchar(max)"); - - b.Property("PrimaryContactEmail") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); - - b.Property("PrimaryPhoneNumber") - .HasMaxLength(20) - .HasColumnType("nvarchar(20)"); - - b.Property("SecondaryPhoneNumber") - .HasMaxLength(20) - .HasColumnType("nvarchar(20)"); - - b.Property("ShowTeamAnnouncement") - .HasColumnType("bit"); - - b.HasKey("ID"); - - b.HasIndex("EventID"); - - b.ToTable("Teams"); - }); - - modelBuilder.Entity("ServerCore.DataModel.TeamApplication", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("PlayerID") - .HasColumnType("int"); - - b.Property("TeamID") - .HasColumnType("int"); - - b.HasKey("ID"); - - b.HasIndex("PlayerID"); - - b.HasIndex("TeamID"); - - b.ToTable("TeamApplications"); - }); - - modelBuilder.Entity("ServerCore.DataModel.TeamLunch", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("Lunch") - .HasColumnType("nvarchar(max)"); - - b.Property("LunchModifications") - .HasMaxLength(500) - .HasColumnType("nvarchar(500)"); - - b.Property("TeamId") - .HasColumnType("int"); - - b.HasKey("ID"); - - b.HasIndex("TeamId"); - - b.ToTable("TeamLunch"); - }); - - modelBuilder.Entity("ServerCore.DataModel.TeamMembers", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); - - b.Property("ClassID") - .HasColumnType("int"); - - b.Property("Team.ID") - .HasColumnType("int"); - - b.Property("TemporaryClassID") - .HasColumnType("int"); - - b.Property("User.ID") - .HasColumnType("int"); - - b.HasKey("ID"); - - b.HasIndex("ClassID"); - - b.HasIndex("ID"); - - b.HasIndex("Team.ID"); - - b.HasIndex("TemporaryClassID"); - - b.HasIndex("User.ID"); - - b.ToTable("TeamMembers"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("ServerCore.DataModel.Annotation", b => - { - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany() - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Team", "Team") - .WithMany() - .HasForeignKey("TeamID") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Puzzle"); - - b.Navigation("Team"); - }); - - modelBuilder.Entity("ServerCore.DataModel.ContentFile", b => - { - b.HasOne("ServerCore.DataModel.Event", "Event") - .WithMany() - .HasForeignKey("EventID") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany("Contents") - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Event"); - - b.Navigation("Puzzle"); - }); - - modelBuilder.Entity("ServerCore.DataModel.EventAdmins", b => - { - b.HasOne("ServerCore.DataModel.PuzzleUser", "Admin") - .WithMany() - .HasForeignKey("AdminID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Event", "Event") - .WithMany() - .HasForeignKey("EventID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Admin"); - - b.Navigation("Event"); - }); - - modelBuilder.Entity("ServerCore.DataModel.EventAuthors", b => - { - b.HasOne("ServerCore.DataModel.PuzzleUser", "Author") - .WithMany() - .HasForeignKey("AuthorID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Event", "Event") - .WithMany() - .HasForeignKey("EventID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Author"); - - b.Navigation("Event"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Feedback", b => - { - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany() - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.PuzzleUser", "Submitter") - .WithMany() - .HasForeignKey("SubmitterID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Puzzle"); - - b.Navigation("Submitter"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Hint", b => - { - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany() - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Puzzle"); - }); - - modelBuilder.Entity("ServerCore.DataModel.HintStatePerTeam", b => - { - b.HasOne("ServerCore.DataModel.Hint", "Hint") - .WithMany() - .HasForeignKey("HintID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Team", "Team") - .WithMany() - .HasForeignKey("TeamID") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Hint"); - - b.Navigation("Team"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Invitation", b => - { - b.HasOne("ServerCore.DataModel.Team", null) - .WithMany("Invitations") - .HasForeignKey("TeamID"); - }); - - modelBuilder.Entity("ServerCore.DataModel.LiveEvent", b => - { - b.HasOne("ServerCore.DataModel.Puzzle", "AssociatedPuzzle") - .WithMany() - .HasForeignKey("AssociatedPuzzleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("AssociatedPuzzle"); - }); - - modelBuilder.Entity("ServerCore.DataModel.LiveEventSchedule", b => - { - b.HasOne("ServerCore.DataModel.LiveEvent", "LiveEvent") - .WithMany() - .HasForeignKey("LiveEventId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Team", "Team") - .WithMany() - .HasForeignKey("TeamId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("LiveEvent"); - - b.Navigation("Team"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Message", b => - { - b.HasOne("ServerCore.DataModel.PuzzleUser", "Claimer") - .WithMany() - .HasForeignKey("ClaimerID") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("ServerCore.DataModel.Event", "Event") - .WithMany() - .HasForeignKey("EventID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") - .WithMany() - .HasForeignKey("PlayerID") - .OnDelete(DeleteBehavior.Restrict); - - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany() - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Restrict); - - b.HasOne("ServerCore.DataModel.PuzzleUser", "Sender") - .WithMany() - .HasForeignKey("SenderID") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Team", "Team") - .WithMany() - .HasForeignKey("TeamID") - .OnDelete(DeleteBehavior.Restrict); - - b.Navigation("Claimer"); - - b.Navigation("Event"); - - b.Navigation("Player"); - - b.Navigation("Puzzle"); - - b.Navigation("Sender"); - - b.Navigation("Team"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Piece", b => - { - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany() - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Puzzle"); - }); - - modelBuilder.Entity("ServerCore.DataModel.PlayerClass", b => - { - b.HasOne("ServerCore.DataModel.Event", "Event") - .WithMany() - .HasForeignKey("EventID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Event"); - }); - - modelBuilder.Entity("ServerCore.DataModel.PlayerInEvent", b => - { - b.HasOne("ServerCore.DataModel.Event", "Event") - .WithMany() - .HasForeignKey("EventId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") - .WithMany() - .HasForeignKey("PlayerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Event"); - - b.Navigation("Player"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Prerequisites", b => - { - b.HasOne("ServerCore.DataModel.Puzzle", "Prerequisite") - .WithMany() - .HasForeignKey("PrerequisiteID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany() - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Prerequisite"); - - b.Navigation("Puzzle"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Puzzle", b => - { - b.HasOne("ServerCore.DataModel.Event", "Event") - .WithMany() - .HasForeignKey("EventID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Event"); - }); - - modelBuilder.Entity("ServerCore.DataModel.PuzzleAuthors", b => - { - b.HasOne("ServerCore.DataModel.PuzzleUser", "Author") - .WithMany() - .HasForeignKey("AuthorID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany() - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Author"); - - b.Navigation("Puzzle"); - }); - - modelBuilder.Entity("ServerCore.DataModel.PuzzleStatePerTeam", b => - { - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany() - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Team", "Team") - .WithMany() - .HasForeignKey("TeamID") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Puzzle"); - - b.Navigation("Team"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Response", b => - { - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany() - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Puzzle"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Room", b => - { - b.HasOne("ServerCore.DataModel.Event", "Event") - .WithMany() - .HasForeignKey("EventID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Team", "Team") - .WithMany() - .HasForeignKey("TeamID"); - - b.Navigation("Event"); - - b.Navigation("Team"); - }); - - modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleHintStatePerPlayer", b => - { - b.HasOne("ServerCore.DataModel.Hint", "Hint") - .WithMany() - .HasForeignKey("HintID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") - .WithMany() - .HasForeignKey("PlayerID") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Hint"); - - b.Navigation("Player"); - }); - - modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleStatePerPlayer", b => - { - b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") - .WithMany() - .HasForeignKey("PlayerID") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany() - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Player"); - - b.Navigation("Puzzle"); - }); - - modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleSubmission", b => - { - b.HasOne("ServerCore.DataModel.PuzzleUser", "FreeformJudge") - .WithMany() - .HasForeignKey("FreeformJudgeID"); - - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany("SinglePlayerPuzzleSubmissions") - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Response", "Response") - .WithMany() - .HasForeignKey("ResponseID"); - - b.HasOne("ServerCore.DataModel.PuzzleUser", "Submitter") - .WithMany() - .HasForeignKey("SubmitterID") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("FreeformJudge"); - - b.Navigation("Puzzle"); - - b.Navigation("Response"); - - b.Navigation("Submitter"); - }); - - modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleUnlockState", b => - { - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany() - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Puzzle"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Submission", b => - { - b.HasOne("ServerCore.DataModel.PuzzleUser", "FreeformJudge") - .WithMany() - .HasForeignKey("FreeformJudgeID"); - - b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") - .WithMany("Submissions") - .HasForeignKey("PuzzleID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Response", "Response") - .WithMany() - .HasForeignKey("ResponseID"); - - b.HasOne("ServerCore.DataModel.PuzzleUser", "Submitter") - .WithMany() - .HasForeignKey("SubmitterID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Team", "Team") - .WithMany() - .HasForeignKey("TeamID") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Team", null) - .WithMany("Submissions") - .HasForeignKey("TeamID1"); - - b.Navigation("FreeformJudge"); - - b.Navigation("Puzzle"); - - b.Navigation("Response"); - - b.Navigation("Submitter"); - - b.Navigation("Team"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Team", b => - { - b.HasOne("ServerCore.DataModel.Event", "Event") - .WithMany() - .HasForeignKey("EventID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Event"); - }); - - modelBuilder.Entity("ServerCore.DataModel.TeamApplication", b => - { - b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") - .WithMany() - .HasForeignKey("PlayerID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.Team", "Team") - .WithMany() - .HasForeignKey("TeamID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Player"); - - b.Navigation("Team"); - }); - - modelBuilder.Entity("ServerCore.DataModel.TeamLunch", b => - { - b.HasOne("ServerCore.DataModel.Team", "Team") - .WithMany() - .HasForeignKey("TeamId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Team"); - }); - - modelBuilder.Entity("ServerCore.DataModel.TeamMembers", b => - { - b.HasOne("ServerCore.DataModel.PlayerClass", "Class") - .WithMany() - .HasForeignKey("ClassID"); - - b.HasOne("ServerCore.DataModel.Team", "Team") - .WithMany() - .HasForeignKey("Team.ID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("ServerCore.DataModel.PlayerClass", "TemporaryClass") - .WithMany() - .HasForeignKey("TemporaryClassID"); - - b.HasOne("ServerCore.DataModel.PuzzleUser", "Member") - .WithMany() - .HasForeignKey("User.ID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Class"); - - b.Navigation("Member"); - - b.Navigation("Team"); - - b.Navigation("TemporaryClass"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Puzzle", b => - { - b.Navigation("Contents"); - - b.Navigation("SinglePlayerPuzzleSubmissions"); - - b.Navigation("Submissions"); - }); - - modelBuilder.Entity("ServerCore.DataModel.Team", b => - { - b.Navigation("Invitations"); - - b.Navigation("Submissions"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Data/Migrations/20260512223806_DbIndexImprovements.cs b/Data/Migrations/20260512223806_DbIndexImprovements.cs deleted file mode 100644 index 7dc0007e..00000000 --- a/Data/Migrations/20260512223806_DbIndexImprovements.cs +++ /dev/null @@ -1,169 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Data.Migrations -{ - /// - public partial class DbIndexImprovements : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_Swag_PlayerId", - table: "Swag"); - - migrationBuilder.DropIndex( - name: "IX_Pieces_ProgressLevel", - table: "Pieces"); - - migrationBuilder.DropIndex( - name: "IX_EventAuthors_AuthorID", - table: "EventAuthors"); - - migrationBuilder.DropIndex( - name: "IX_EventAdmins_AdminID", - table: "EventAdmins"); - - migrationBuilder.AlterColumn( - name: "IdentityUserId", - table: "PuzzleUsers", - type: "nvarchar(450)", - maxLength: 450, - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(max)"); - - migrationBuilder.AddColumn( - name: "PuzzleListCustomHeaderUrl", - table: "Events", - type: "nvarchar(max)", - nullable: true); - - migrationBuilder.CreateIndex( - name: "IX_TeamMembers_UserID_TeamID", - table: "TeamMembers", - columns: new[] { "User.ID", "Team.ID" }) - .Annotation("SqlServer:Include", new[] { "ID", "ClassID", "TemporaryClassID" }); - - migrationBuilder.CreateIndex( - name: "IX_Swag_PlayerId_EventId", - table: "Swag", - columns: new[] { "PlayerId", "EventId" }); - - migrationBuilder.CreateIndex( - name: "IX_PuzzleUsers_IdentityUserId", - table: "PuzzleUsers", - column: "IdentityUserId"); - - migrationBuilder.CreateIndex( - name: "IX_Puzzles_MinutesOfEventLockout_Availability_ID", - table: "Puzzles", - columns: new[] { "MinutesOfEventLockout", "Availability", "ID" }); - - migrationBuilder.CreateIndex( - name: "IX_Puzzles_MinutesToAutomaticallySolve_Availability_ID", - table: "Puzzles", - columns: new[] { "MinutesToAutomaticallySolve", "Availability", "ID" }); - - migrationBuilder.CreateIndex( - name: "IX_Pieces_ProgressLevel_PuzzleID", - table: "Pieces", - columns: new[] { "ProgressLevel", "PuzzleID" }) - .Annotation("SqlServer:Include", new[] { "ID", "Contents" }); - - migrationBuilder.CreateIndex( - name: "IX_EventAuthors_AuthorID_EventID", - table: "EventAuthors", - columns: new[] { "AuthorID", "EventID" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_EventAdmins_AdminID_EventID", - table: "EventAdmins", - columns: new[] { "AdminID", "EventID" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ContentFiles_EventID_FileType", - table: "ContentFiles", - columns: new[] { "EventID", "FileType" }, - unique: true) - .Annotation("SqlServer:Include", new[] { "ShortName", "UrlString", "PuzzleID" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_TeamMembers_UserID_TeamID", - table: "TeamMembers"); - - migrationBuilder.DropIndex( - name: "IX_Swag_PlayerId_EventId", - table: "Swag"); - - migrationBuilder.DropIndex( - name: "IX_PuzzleUsers_IdentityUserId", - table: "PuzzleUsers"); - - migrationBuilder.DropIndex( - name: "IX_Puzzles_MinutesOfEventLockout_Availability_ID", - table: "Puzzles"); - - migrationBuilder.DropIndex( - name: "IX_Puzzles_MinutesToAutomaticallySolve_Availability_ID", - table: "Puzzles"); - - migrationBuilder.DropIndex( - name: "IX_Pieces_ProgressLevel_PuzzleID", - table: "Pieces"); - - migrationBuilder.DropIndex( - name: "IX_EventAuthors_AuthorID_EventID", - table: "EventAuthors"); - - migrationBuilder.DropIndex( - name: "IX_EventAdmins_AdminID_EventID", - table: "EventAdmins"); - - migrationBuilder.DropIndex( - name: "IX_ContentFiles_EventID_FileType", - table: "ContentFiles"); - - migrationBuilder.DropColumn( - name: "PuzzleListCustomHeaderUrl", - table: "Events"); - - migrationBuilder.AlterColumn( - name: "IdentityUserId", - table: "PuzzleUsers", - type: "nvarchar(max)", - nullable: false, - oldClrType: typeof(string), - oldType: "nvarchar(450)", - oldMaxLength: 450); - - migrationBuilder.CreateIndex( - name: "IX_Swag_PlayerId", - table: "Swag", - column: "PlayerId"); - - migrationBuilder.CreateIndex( - name: "IX_Pieces_ProgressLevel", - table: "Pieces", - column: "ProgressLevel"); - - migrationBuilder.CreateIndex( - name: "IX_EventAuthors_AuthorID", - table: "EventAuthors", - column: "AuthorID"); - - migrationBuilder.CreateIndex( - name: "IX_EventAdmins_AdminID", - table: "EventAdmins", - column: "AdminID"); - } - } -} diff --git a/Data/Migrations/PuzzleServerContextModelSnapshot.cs b/Data/Migrations/PuzzleServerContextModelSnapshot.cs index 90ba741d..09d3690b 100644 --- a/Data/Migrations/PuzzleServerContextModelSnapshot.cs +++ b/Data/Migrations/PuzzleServerContextModelSnapshot.cs @@ -170,11 +170,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.Property("LoginProvider") - .HasMaxLength(450) .HasColumnType("nvarchar(450)"); b.Property("ProviderKey") - .HasMaxLength(450) .HasColumnType("nvarchar(450)"); b.Property("ProviderDisplayName") @@ -212,11 +210,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(450)"); b.Property("LoginProvider") - .HasMaxLength(450) .HasColumnType("nvarchar(450)"); b.Property("Name") - .HasMaxLength(450) .HasColumnType("nvarchar(450)"); b.Property("Value") @@ -253,7 +249,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamID"); - b.ToTable("Annotations"); + b.ToTable("Annotations", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.ContentFile", b => @@ -285,15 +281,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); - b.HasIndex("EventID", "FileType") - .IsUnique(); - - SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("EventID", "FileType"), new[] { "ShortName", "UrlString", "PuzzleID" }); - b.HasIndex("EventID", "ShortName") .IsUnique(); - b.ToTable("ContentFiles"); + b.ToTable("ContentFiles", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Event", b => @@ -442,9 +433,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PlayersPerLunch") .HasColumnType("int"); - b.Property("PuzzleListCustomHeaderUrl") - .HasColumnType("nvarchar(max)"); - b.Property("PuzzleSyncEnabled") .HasColumnType("bit"); @@ -493,7 +481,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsUnique() .HasFilter("[UrlString] IS NOT NULL"); - b.ToTable("Events"); + b.ToTable("Events", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.EventAdmins", b => @@ -512,12 +500,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); - b.HasIndex("EventID"); + b.HasIndex("AdminID"); - b.HasIndex("AdminID", "EventID") - .IsUnique(); + b.HasIndex("EventID"); - b.ToTable("EventAdmins"); + b.ToTable("EventAdmins", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.EventAuthors", b => @@ -536,12 +523,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); - b.HasIndex("EventID"); + b.HasIndex("AuthorID"); - b.HasIndex("AuthorID", "EventID") - .IsUnique(); + b.HasIndex("EventID"); - b.ToTable("EventAuthors"); + b.ToTable("EventAuthors", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Feedback", b => @@ -576,7 +562,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("SubmitterID"); - b.ToTable("Feedback"); + b.ToTable("Feedback", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Hint", b => @@ -608,7 +594,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); - b.ToTable("Hints"); + b.ToTable("Hints", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.HintStatePerTeam", b => @@ -626,7 +612,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("HintID"); - b.ToTable("HintStatePerTeam"); + b.ToTable("HintStatePerTeam", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Invitation", b => @@ -656,7 +642,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamID"); - b.ToTable("Invitations"); + b.ToTable("Invitations", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.LiveEvent", b => @@ -718,7 +704,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("AssociatedPuzzleId"); - b.ToTable("LiveEvents"); + b.ToTable("LiveEvents", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.LiveEventSchedule", b => @@ -747,7 +733,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamId"); - b.ToTable("LiveEventsSchedule"); + b.ToTable("LiveEventsSchedule", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Message", b => @@ -812,7 +798,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ThreadId"); - b.ToTable("Messages"); + b.ToTable("Messages", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Piece", b => @@ -835,13 +821,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); - b.HasIndex("PuzzleID"); - - b.HasIndex("ProgressLevel", "PuzzleID"); + b.HasIndex("ProgressLevel"); - SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("ProgressLevel", "PuzzleID"), new[] { "ID", "Contents" }); + b.HasIndex("PuzzleID"); - b.ToTable("Pieces"); + b.ToTable("Pieces", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.PlayerClass", b => @@ -872,7 +856,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventID"); - b.ToTable("PlayerClasses"); + b.ToTable("PlayerClasses", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.PlayerInEvent", b => @@ -913,9 +897,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventId"); - b.HasIndex("PlayerId", "EventId"); + b.HasIndex("PlayerId"); - b.ToTable("Swag"); + b.ToTable("Swag", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Prerequisites", b => @@ -938,7 +922,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); - b.ToTable("Prerequisites"); + b.ToTable("Prerequisites", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Puzzle", b => @@ -1068,11 +1052,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventID"); - b.HasIndex("MinutesOfEventLockout", "Availability", "ID"); - - b.HasIndex("MinutesToAutomaticallySolve", "Availability", "ID"); - - b.ToTable("Puzzles"); + b.ToTable("Puzzles", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.PuzzleAuthors", b => @@ -1098,7 +1078,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); - b.ToTable("PuzzleAuthors"); + b.ToTable("PuzzleAuthors", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.PuzzleStatePerTeam", b => @@ -1139,7 +1119,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamID", "SolvedTime"); - b.ToTable("PuzzleStatePerTeam"); + b.ToTable("PuzzleStatePerTeam", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.PuzzleUser", b => @@ -1161,8 +1141,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("IdentityUserId") .IsRequired() - .HasMaxLength(450) - .HasColumnType("nvarchar(450)"); + .HasColumnType("nvarchar(max)"); b.Property("IsGlobalAdmin") .HasColumnType("bit"); @@ -1188,9 +1167,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); - b.HasIndex("IdentityUserId"); - - b.ToTable("PuzzleUsers"); + b.ToTable("PuzzleUsers", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Response", b => @@ -1223,7 +1200,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); - b.ToTable("Responses"); + b.ToTable("Responses", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Room", b => @@ -1264,7 +1241,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsUnique() .HasFilter("[Building] IS NOT NULL"); - b.ToTable("Rooms"); + b.ToTable("Rooms", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleHintStatePerPlayer", b => @@ -1282,7 +1259,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("HintID"); - b.ToTable("SinglePlayerPuzzleHintStatePerPlayer"); + b.ToTable("SinglePlayerPuzzleHintStatePerPlayer", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleStatePerPlayer", b => @@ -1323,7 +1300,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PlayerID", "SolvedTime"); - b.ToTable("SinglePlayerPuzzleStatePerPlayer"); + b.ToTable("SinglePlayerPuzzleStatePerPlayer", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleSubmission", b => @@ -1380,7 +1357,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("SubmitterID", "PuzzleID", "SubmissionText") .IsUnique(); - b.ToTable("SinglePlayerPuzzleSubmissions"); + b.ToTable("SinglePlayerPuzzleSubmissions", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleUnlockState", b => @@ -1393,7 +1370,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("PuzzleID"); - b.ToTable("SinglePlayerPuzzleUnlockStates"); + b.ToTable("SinglePlayerPuzzleUnlockStates", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Submission", b => @@ -1460,7 +1437,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamID", "PuzzleID", "SubmissionText") .IsUnique(); - b.ToTable("Submissions"); + b.ToTable("Submissions", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.Team", b => @@ -1534,7 +1511,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventID"); - b.ToTable("Teams"); + b.ToTable("Teams", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.TeamApplication", b => @@ -1557,7 +1534,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamID"); - b.ToTable("TeamApplications"); + b.ToTable("TeamApplications", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.TeamLunch", b => @@ -1582,7 +1559,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamId"); - b.ToTable("TeamLunch"); + b.ToTable("TeamLunch", (string)null); }); modelBuilder.Entity("ServerCore.DataModel.TeamMembers", b => @@ -1609,15 +1586,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ClassID"); - b.HasIndex("ID"); - b.HasIndex("Team.ID"); b.HasIndex("TemporaryClassID"); b.HasIndex("User.ID"); - b.ToTable("TeamMembers"); + b.ToTable("TeamMembers", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => diff --git a/Data/PuzzleServerContext.cs b/Data/PuzzleServerContext.cs index e15d1ffc..d72495ad 100644 --- a/Data/PuzzleServerContext.cs +++ b/Data/PuzzleServerContext.cs @@ -68,7 +68,7 @@ public static void UpdateDatabase(IApplicationBuilder app) protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().HasIndex(contentFile => new { contentFile.EventID, contentFile.ShortName }).IsUnique(); - modelBuilder.Entity().HasIndex(contentFile => new { contentFile.EventID, contentFile.FileType}).IncludeProperties(contentFile => new { contentFile.ShortName, contentFile.UrlString, contentFile.PuzzleID}).IsUnique(); + modelBuilder.Entity().HasIndex(contentFile => new { contentFile.EventID, contentFile.FileType}).IncludeProperties(contentFile => new { contentFile.ShortName, contentFile.UrlString, contentFile.PuzzleID}); modelBuilder.Entity().HasKey(state => new { state.PuzzleID, state.TeamID }); modelBuilder.Entity().HasKey(state => new { state.TeamID, state.HintID }); modelBuilder.Entity().HasKey(state => new { state.PlayerID, state.HintID }); @@ -90,7 +90,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasIndex(room => new { room.EventID, room.Building, room.Number }).IsUnique(); modelBuilder.Entity().HasIndex(pie => new { pie.PlayerId, pie.EventId}); modelBuilder.Entity().HasIndex(pu => new { pu.IdentityUserId}); - modelBuilder.Entity().HasIndex(tm => new { tm.ID }); //EF can't parse this for nested types, so this is a placeholder to manually edit the generated model to INDEX Team.ID, User.ID, INCLUDE Class.ID, ID, TemporaryClassID + modelBuilder.Entity().HasIndex(tm => new { tm.TeamID, tm.MemberID }).IncludeProperties(tm => new { tm.ID, tm.ClassID, tm.TemporaryClassID}); modelBuilder.Entity().HasIndex(message => message.ThreadId); modelBuilder.Entity().HasIndex(message => message.EventID); modelBuilder.Entity().HasIndex(message => message.PuzzleID); From 803a680c07f7e9933d061562bd33b1c954940bea Mon Sep 17 00:00:00 2001 From: Roger Date: Wed, 20 May 2026 22:18:13 -0700 Subject: [PATCH 3/4] Get snapshot in sync --- .../PuzzleServerContextModelSnapshot.cs | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/Data/Migrations/PuzzleServerContextModelSnapshot.cs b/Data/Migrations/PuzzleServerContextModelSnapshot.cs index 09d3690b..a33d239b 100644 --- a/Data/Migrations/PuzzleServerContextModelSnapshot.cs +++ b/Data/Migrations/PuzzleServerContextModelSnapshot.cs @@ -170,9 +170,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.Property("LoginProvider") + .HasMaxLength(450) .HasColumnType("nvarchar(450)"); b.Property("ProviderKey") + .HasMaxLength(450) .HasColumnType("nvarchar(450)"); b.Property("ProviderDisplayName") @@ -210,9 +212,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(450)"); b.Property("LoginProvider") + .HasMaxLength(450) .HasColumnType("nvarchar(450)"); b.Property("Name") + .HasMaxLength(450) .HasColumnType("nvarchar(450)"); b.Property("Value") @@ -249,7 +253,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamID"); - b.ToTable("Annotations", (string)null); + b.ToTable("Annotations"); }); modelBuilder.Entity("ServerCore.DataModel.ContentFile", b => @@ -284,7 +288,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventID", "ShortName") .IsUnique(); - b.ToTable("ContentFiles", (string)null); + b.ToTable("ContentFiles"); }); modelBuilder.Entity("ServerCore.DataModel.Event", b => @@ -433,6 +437,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PlayersPerLunch") .HasColumnType("int"); + b.Property("PuzzleListCustomHeaderUrl") + .HasColumnType("nvarchar(max)"); + b.Property("PuzzleSyncEnabled") .HasColumnType("bit"); @@ -481,7 +488,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsUnique() .HasFilter("[UrlString] IS NOT NULL"); - b.ToTable("Events", (string)null); + b.ToTable("Events"); }); modelBuilder.Entity("ServerCore.DataModel.EventAdmins", b => @@ -504,7 +511,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventID"); - b.ToTable("EventAdmins", (string)null); + b.ToTable("EventAdmins"); }); modelBuilder.Entity("ServerCore.DataModel.EventAuthors", b => @@ -527,7 +534,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventID"); - b.ToTable("EventAuthors", (string)null); + b.ToTable("EventAuthors"); }); modelBuilder.Entity("ServerCore.DataModel.Feedback", b => @@ -562,7 +569,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("SubmitterID"); - b.ToTable("Feedback", (string)null); + b.ToTable("Feedback"); }); modelBuilder.Entity("ServerCore.DataModel.Hint", b => @@ -594,7 +601,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); - b.ToTable("Hints", (string)null); + b.ToTable("Hints"); }); modelBuilder.Entity("ServerCore.DataModel.HintStatePerTeam", b => @@ -612,7 +619,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("HintID"); - b.ToTable("HintStatePerTeam", (string)null); + b.ToTable("HintStatePerTeam"); }); modelBuilder.Entity("ServerCore.DataModel.Invitation", b => @@ -642,7 +649,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamID"); - b.ToTable("Invitations", (string)null); + b.ToTable("Invitations"); }); modelBuilder.Entity("ServerCore.DataModel.LiveEvent", b => @@ -704,7 +711,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("AssociatedPuzzleId"); - b.ToTable("LiveEvents", (string)null); + b.ToTable("LiveEvents"); }); modelBuilder.Entity("ServerCore.DataModel.LiveEventSchedule", b => @@ -733,7 +740,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamId"); - b.ToTable("LiveEventsSchedule", (string)null); + b.ToTable("LiveEventsSchedule"); }); modelBuilder.Entity("ServerCore.DataModel.Message", b => @@ -798,7 +805,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("ThreadId"); - b.ToTable("Messages", (string)null); + b.ToTable("Messages"); }); modelBuilder.Entity("ServerCore.DataModel.Piece", b => @@ -825,7 +832,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); - b.ToTable("Pieces", (string)null); + b.ToTable("Pieces"); }); modelBuilder.Entity("ServerCore.DataModel.PlayerClass", b => @@ -856,7 +863,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventID"); - b.ToTable("PlayerClasses", (string)null); + b.ToTable("PlayerClasses"); }); modelBuilder.Entity("ServerCore.DataModel.PlayerInEvent", b => @@ -899,7 +906,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PlayerId"); - b.ToTable("Swag", (string)null); + b.ToTable("Swag"); }); modelBuilder.Entity("ServerCore.DataModel.Prerequisites", b => @@ -922,7 +929,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); - b.ToTable("Prerequisites", (string)null); + b.ToTable("Prerequisites"); }); modelBuilder.Entity("ServerCore.DataModel.Puzzle", b => @@ -1052,7 +1059,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventID"); - b.ToTable("Puzzles", (string)null); + b.ToTable("Puzzles"); }); modelBuilder.Entity("ServerCore.DataModel.PuzzleAuthors", b => @@ -1078,7 +1085,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); - b.ToTable("PuzzleAuthors", (string)null); + b.ToTable("PuzzleAuthors"); }); modelBuilder.Entity("ServerCore.DataModel.PuzzleStatePerTeam", b => @@ -1119,7 +1126,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamID", "SolvedTime"); - b.ToTable("PuzzleStatePerTeam", (string)null); + b.ToTable("PuzzleStatePerTeam"); }); modelBuilder.Entity("ServerCore.DataModel.PuzzleUser", b => @@ -1167,7 +1174,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); - b.ToTable("PuzzleUsers", (string)null); + b.ToTable("PuzzleUsers"); }); modelBuilder.Entity("ServerCore.DataModel.Response", b => @@ -1200,7 +1207,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); - b.ToTable("Responses", (string)null); + b.ToTable("Responses"); }); modelBuilder.Entity("ServerCore.DataModel.Room", b => @@ -1241,7 +1248,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsUnique() .HasFilter("[Building] IS NOT NULL"); - b.ToTable("Rooms", (string)null); + b.ToTable("Rooms"); }); modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleHintStatePerPlayer", b => @@ -1259,7 +1266,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("HintID"); - b.ToTable("SinglePlayerPuzzleHintStatePerPlayer", (string)null); + b.ToTable("SinglePlayerPuzzleHintStatePerPlayer"); }); modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleStatePerPlayer", b => @@ -1300,7 +1307,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PlayerID", "SolvedTime"); - b.ToTable("SinglePlayerPuzzleStatePerPlayer", (string)null); + b.ToTable("SinglePlayerPuzzleStatePerPlayer"); }); modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleSubmission", b => @@ -1357,7 +1364,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("SubmitterID", "PuzzleID", "SubmissionText") .IsUnique(); - b.ToTable("SinglePlayerPuzzleSubmissions", (string)null); + b.ToTable("SinglePlayerPuzzleSubmissions"); }); modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleUnlockState", b => @@ -1370,7 +1377,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("PuzzleID"); - b.ToTable("SinglePlayerPuzzleUnlockStates", (string)null); + b.ToTable("SinglePlayerPuzzleUnlockStates"); }); modelBuilder.Entity("ServerCore.DataModel.Submission", b => @@ -1437,7 +1444,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamID", "PuzzleID", "SubmissionText") .IsUnique(); - b.ToTable("Submissions", (string)null); + b.ToTable("Submissions"); }); modelBuilder.Entity("ServerCore.DataModel.Team", b => @@ -1511,7 +1518,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventID"); - b.ToTable("Teams", (string)null); + b.ToTable("Teams"); }); modelBuilder.Entity("ServerCore.DataModel.TeamApplication", b => @@ -1534,7 +1541,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamID"); - b.ToTable("TeamApplications", (string)null); + b.ToTable("TeamApplications"); }); modelBuilder.Entity("ServerCore.DataModel.TeamLunch", b => @@ -1559,7 +1566,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TeamId"); - b.ToTable("TeamLunch", (string)null); + b.ToTable("TeamLunch"); }); modelBuilder.Entity("ServerCore.DataModel.TeamMembers", b => @@ -1592,7 +1599,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("User.ID"); - b.ToTable("TeamMembers", (string)null); + b.ToTable("TeamMembers"); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => From 3687663c3b4ab8d6b062526e29f8de62042de7e2 Mon Sep 17 00:00:00 2001 From: Roger Date: Wed, 20 May 2026 22:39:35 -0700 Subject: [PATCH 4/4] data model changes --- ...0521051857_DbIndexImprovements.Designer.cs | 2237 +++++++++++++++++ .../20260521051857_DbIndexImprovements.cs | 167 ++ .../PuzzleServerContextModelSnapshot.cs | 63 +- 3 files changed, 2445 insertions(+), 22 deletions(-) create mode 100644 Data/Migrations/20260521051857_DbIndexImprovements.Designer.cs create mode 100644 Data/Migrations/20260521051857_DbIndexImprovements.cs diff --git a/Data/Migrations/20260521051857_DbIndexImprovements.Designer.cs b/Data/Migrations/20260521051857_DbIndexImprovements.Designer.cs new file mode 100644 index 00000000..5ac38625 --- /dev/null +++ b/Data/Migrations/20260521051857_DbIndexImprovements.Designer.cs @@ -0,0 +1,2237 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using ServerCore.DataModel; + +#nullable disable + +namespace Data.Migrations +{ + [DbContext(typeof(PuzzleServerContext))] + [Migration("20260521051857_DbIndexImprovements")] + partial class DbIndexImprovements + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.5") + .HasAnnotation("Proxies:ChangeTracking", false) + .HasAnnotation("Proxies:CheckEquality", false) + .HasAnnotation("Proxies:LazyLoading", true) + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("ServerCore.DataModel.Annotation", b => + { + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.Property("Key") + .HasColumnType("int"); + + b.Property("Contents") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Timestamp") + .HasColumnType("datetime2"); + + b.Property("Version") + .HasColumnType("int"); + + b.HasKey("PuzzleID", "TeamID", "Key"); + + b.HasIndex("TeamID"); + + b.ToTable("Annotations"); + }); + + modelBuilder.Entity("ServerCore.DataModel.ContentFile", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("FileType") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("UrlString") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("ID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("EventID", "FileType"); + + SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("EventID", "FileType"), new[] { "ShortName", "UrlString", "PuzzleID" }); + + b.HasIndex("EventID", "ShortName") + .IsUnique(); + + b.ToTable("ContentFiles"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Event", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AllowFeedback") + .HasColumnType("bit"); + + b.Property("AllowsRemotePlayers") + .HasColumnType("bit") + .HasColumnName("AllowsRemote"); + + b.Property("AllowsRemoteTeams") + .HasColumnType("bit"); + + b.Property("Announcement") + .HasColumnType("nvarchar(max)"); + + b.Property("AnswerSubmissionEnd") + .HasColumnType("datetime2"); + + b.Property("AnswersAvailableBegin") + .HasColumnType("datetime2"); + + b.Property("ContactEmail") + .HasColumnType("nvarchar(max)"); + + b.Property("Copyright") + .HasColumnType("nvarchar(max)"); + + b.Property("DefaultCostForHelpThread") + .HasColumnType("int"); + + b.Property("DefaultLunch") + .HasColumnType("nvarchar(max)"); + + b.Property("EphemeralHacks") + .HasColumnType("nvarchar(max)"); + + b.Property("EventBegin") + .HasColumnType("datetime2"); + + b.Property("EventHasTeamSwag") + .HasColumnType("bit"); + + b.Property("EventPassword") + .HasColumnType("nvarchar(max)"); + + b.Property("FAQContent") + .HasColumnType("nvarchar(max)"); + + b.Property("FastestSyncIntervalMs") + .HasColumnType("int"); + + b.Property("HasIndividualLunch") + .HasColumnType("bit"); + + b.Property("HasPlayerClasses") + .HasColumnType("bit"); + + b.Property("HasSwag") + .HasColumnType("bit") + .HasColumnName("EventHasSwag"); + + b.Property("HasTShirts") + .HasColumnType("bit"); + + b.Property("HideHints") + .HasColumnType("bit"); + + b.Property("HideSolveCounts") + .HasColumnType("bit"); + + b.Property("HideStandings") + .HasColumnType("bit"); + + b.Property("HomeContent") + .HasColumnType("nvarchar(max)"); + + b.Property("HomePartial") + .HasColumnType("nvarchar(max)"); + + b.Property("IsAlphaTestingEvent") + .HasColumnType("bit"); + + b.Property("IsInternEvent") + .HasColumnType("bit"); + + b.Property("IsRemote") + .HasColumnType("bit"); + + b.Property("LockChangesToRemoteStatus") + .HasColumnType("bit"); + + b.Property("LockoutDurationMultiplier") + .HasColumnType("float"); + + b.Property("LockoutIncorrectGuessLimit") + .HasColumnType("int"); + + b.Property("LockoutIncorrectGuessPeriod") + .HasColumnType("float"); + + b.Property("LunchDescription") + .HasColumnType("nvarchar(max)"); + + b.Property("LunchOptions") + .HasColumnType("nvarchar(max)"); + + b.Property("LunchOptionsPerLunch") + .HasColumnType("int"); + + b.Property("LunchReportDate") + .HasColumnType("datetime2"); + + b.Property("MaxExternalsPerTeam") + .HasColumnType("int"); + + b.Property("MaxNumberOfLocalTeams") + .HasColumnType("int"); + + b.Property("MaxNumberOfRemoteTeams") + .HasColumnType("int"); + + b.Property("MaxNumberOfTeams") + .HasColumnType("int"); + + b.Property("MaxSubmissionCount") + .HasColumnType("bigint"); + + b.Property("MaxTeamSize") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PlayerClassName") + .HasColumnType("nvarchar(max)"); + + b.Property("PlayersPerLunch") + .HasColumnType("int"); + + b.Property("PuzzleListCustomHeaderUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("PuzzleSyncEnabled") + .HasColumnType("bit"); + + b.Property("RulesContent") + .HasColumnType("nvarchar(max)"); + + b.Property("ShouldSendHelpThreadMailToGameControl") + .HasColumnType("bit"); + + b.Property("ShouldShowHelpMessageOnlyToAuthor") + .HasColumnType("bit"); + + b.Property("SinglePlayerPuzzleTitle") + .HasColumnType("nvarchar(max)"); + + b.Property("TeamAnnouncement") + .HasColumnType("nvarchar(max)"); + + b.Property("TeamDeleteEnd") + .HasColumnType("datetime2"); + + b.Property("TeamMembershipChangeEnd") + .HasColumnType("datetime2"); + + b.Property("TeamMiscDataChangeEnd") + .HasColumnType("datetime2"); + + b.Property("TeamNameChangeEnd") + .HasColumnType("datetime2"); + + b.Property("TeamRegistrationBegin") + .HasColumnType("datetime2"); + + b.Property("TeamRegistrationEnd") + .HasColumnType("datetime2"); + + b.Property("TermForGroup") + .HasColumnType("nvarchar(max)"); + + b.Property("UrlString") + .HasColumnType("nvarchar(450)"); + + b.HasKey("ID"); + + b.HasIndex("UrlString") + .IsUnique() + .HasFilter("[UrlString] IS NOT NULL"); + + b.ToTable("Events"); + }); + + modelBuilder.Entity("ServerCore.DataModel.EventAdmins", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AdminID") + .HasColumnType("int"); + + b.Property("EventID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("EventID"); + + b.HasIndex("AdminID", "EventID") + .IsUnique(); + + b.ToTable("EventAdmins"); + }); + + modelBuilder.Entity("ServerCore.DataModel.EventAuthors", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AuthorID") + .HasColumnType("int"); + + b.Property("EventID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("EventID"); + + b.HasIndex("AuthorID", "EventID") + .IsUnique(); + + b.ToTable("EventAuthors"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Feedback", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("Difficulty") + .HasColumnType("int"); + + b.Property("Fun") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("SubmissionTime") + .HasColumnType("datetime2"); + + b.Property("SubmitterID") + .HasColumnType("int"); + + b.Property("WrittenFeedback") + .HasColumnType("nvarchar(max)"); + + b.HasKey("ID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("SubmitterID"); + + b.ToTable("Feedback"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Hint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Cost") + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PuzzleID"); + + b.ToTable("Hints"); + }); + + modelBuilder.Entity("ServerCore.DataModel.HintStatePerTeam", b => + { + b.Property("TeamID") + .HasColumnType("int"); + + b.Property("HintID") + .HasColumnType("int"); + + b.Property("UnlockTime") + .HasColumnType("datetime2"); + + b.HasKey("TeamID", "HintID"); + + b.HasIndex("HintID"); + + b.ToTable("HintStatePerTeam"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Invitation", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("EmailAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Expiration") + .HasColumnType("datetime2"); + + b.Property("InvitationCode") + .HasColumnType("uniqueidentifier"); + + b.Property("InvitationType") + .HasColumnType("nvarchar(max)"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("TeamID"); + + b.ToTable("Invitations"); + }); + + modelBuilder.Entity("ServerCore.DataModel.LiveEvent", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AssociatedPuzzleId") + .HasColumnType("int"); + + b.Property("ClosingReminderOffset") + .HasColumnType("time"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("EventEndTimeUtc") + .HasColumnType("datetime2"); + + b.Property("EventIsScheduled") + .HasColumnType("bit"); + + b.Property("EventStartTimeUtc") + .HasColumnType("datetime2"); + + b.Property("FirstReminderOffset") + .HasColumnType("time"); + + b.Property("LastNotifiedAllTeamsUtc") + .HasColumnType("datetime2"); + + b.Property("LastReminderOffset") + .HasColumnType("time"); + + b.Property("Location") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NumberOfInstances") + .HasColumnType("int"); + + b.Property("OpeningReminderOffset") + .HasColumnType("time"); + + b.Property("TeamsPerSlot") + .HasColumnType("int"); + + b.Property("TimePerSlot") + .HasColumnType("time"); + + b.HasKey("ID"); + + b.HasIndex("AssociatedPuzzleId"); + + b.ToTable("LiveEvents"); + }); + + modelBuilder.Entity("ServerCore.DataModel.LiveEventSchedule", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("LastNotifiedUtc") + .HasColumnType("datetime2"); + + b.Property("LiveEventId") + .HasColumnType("int"); + + b.Property("StartTimeUtc") + .HasColumnType("datetime2"); + + b.Property("TeamId") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("LiveEventId"); + + b.HasIndex("TeamId"); + + b.ToTable("LiveEventsSchedule"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Message", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("ClaimerID") + .HasColumnType("int"); + + b.Property("CreatedDateTimeInUtc") + .HasColumnType("datetime2"); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("IsFromGameControl") + .HasColumnType("bit"); + + b.Property("ModifiedDateTimeInUtc") + .HasColumnType("datetime2"); + + b.Property("PlayerID") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("SenderID") + .HasColumnType("int"); + + b.Property("Subject") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.Property("Text") + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.Property("ThreadId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("ID"); + + b.HasIndex("ClaimerID"); + + b.HasIndex("EventID"); + + b.HasIndex("PlayerID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("SenderID"); + + b.HasIndex("TeamID"); + + b.HasIndex("ThreadId"); + + b.ToTable("Messages"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Piece", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("Contents") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ProgressLevel") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("ProgressLevel", "PuzzleID"); + + SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("ProgressLevel", "PuzzleID"), new[] { "ID", "Contents" }); + + b.ToTable("Pieces"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PlayerClass", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("UniqueName") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.HasKey("ID"); + + b.HasIndex("EventID"); + + b.ToTable("PlayerClasses"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PlayerInEvent", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("EventId") + .HasColumnType("int"); + + b.Property("HintCoinCount") + .HasColumnType("int"); + + b.Property("HintCoinsUsed") + .HasColumnType("int"); + + b.Property("IsRemote") + .HasColumnType("bit"); + + b.Property("Lunch") + .HasColumnType("nvarchar(max)"); + + b.Property("LunchModifications") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("PlayerId") + .HasColumnType("int"); + + b.Property("ShirtSize") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.HasKey("ID"); + + b.HasIndex("EventId"); + + b.HasIndex("PlayerId", "EventId"); + + b.ToTable("Swag"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Prerequisites", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("PrerequisiteID") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("PrerequisiteID"); + + b.HasIndex("PuzzleID"); + + b.ToTable("Prerequisites"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Puzzle", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AlphaTestsNeeded") + .HasColumnType("int"); + + b.Property("Availability") + .HasColumnType("int"); + + b.Property("CostForHelpThread") + .HasColumnType("int"); + + b.Property("CustomAuthorText") + .HasColumnType("nvarchar(max)"); + + b.Property("CustomCSSFile") + .HasColumnType("nvarchar(max)"); + + b.Property("CustomSolutionURL") + .HasColumnType("nvarchar(max)"); + + b.Property("CustomURL") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Errata") + .HasColumnType("nvarchar(max)"); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("Group") + .HasColumnType("nvarchar(max)"); + + b.Property("HasDataConfirmation") + .HasColumnType("bit"); + + b.Property("HintCoinsForSolve") + .HasColumnType("int"); + + b.Property("HintsAreCumulative") + .HasColumnType("bit"); + + b.Property("IsCheatCode") + .HasColumnType("bit"); + + b.Property("IsFinalPuzzle") + .HasColumnType("bit"); + + b.Property("IsForSinglePlayer") + .HasColumnType("bit"); + + b.Property("IsFreeform") + .HasColumnType("bit"); + + b.Property("IsGloballyVisiblePrerequisite") + .HasColumnType("bit"); + + b.Property("IsMetaPuzzle") + .HasColumnType("bit"); + + b.Property("IsPuzzle") + .HasColumnType("bit"); + + b.Property("MaxAnnotationKey") + .HasColumnType("int"); + + b.Property("MinInGroupCount") + .HasColumnType("int"); + + b.Property("MinPrerequisiteCount") + .HasColumnType("int"); + + b.Property("MinutesOfEventLockout") + .HasColumnType("int"); + + b.Property("MinutesToAutomaticallySolve") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrderInGroup") + .HasColumnType("int"); + + b.Property("PieceMetaTagFilter") + .HasColumnType("nvarchar(max)"); + + b.Property("PieceMetaUsage") + .HasColumnType("int"); + + b.Property("PieceTag") + .HasColumnType("nvarchar(max)"); + + b.Property("PieceWeight") + .HasColumnType("int"); + + b.Property("PrerequisiteWeight") + .HasColumnType("int"); + + b.Property("PuzzleVersion") + .HasColumnType("int"); + + b.Property("ShowHelpThreadsToAllGameControl") + .HasColumnType("bit"); + + b.Property("SolveValue") + .HasColumnType("int"); + + b.Property("SupportEmailAlias") + .HasColumnType("nvarchar(max)"); + + b.Property("Token") + .HasColumnType("nvarchar(max)"); + + b.HasKey("ID"); + + b.HasIndex("EventID"); + + b.HasIndex("MinutesOfEventLockout", "Availability", "ID"); + + b.HasIndex("MinutesToAutomaticallySolve", "Availability", "ID"); + + b.ToTable("Puzzles"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PuzzleAuthors", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AuthorID") + .HasColumnType("int"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("SupportOnly") + .HasColumnType("bit"); + + b.HasKey("ID"); + + b.HasIndex("AuthorID"); + + b.HasIndex("PuzzleID"); + + b.ToTable("PuzzleAuthors"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PuzzleStatePerTeam", b => + { + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.Property("IsEmailOnlyMode") + .HasColumnType("bit"); + + b.Property("IsHelpThreadUnlockedByCoins") + .HasColumnType("bit"); + + b.Property("LockoutExpiryTime") + .HasColumnType("datetime2"); + + b.Property("Notes") + .HasColumnType("nvarchar(max)"); + + b.Property("Printed") + .HasColumnType("bit"); + + b.Property("SolvedTime") + .HasColumnType("datetime2"); + + b.Property("UnlockedTime") + .HasColumnType("datetime2"); + + b.Property("WrongSubmissionCountBuffer") + .HasColumnType("bigint"); + + b.HasKey("PuzzleID", "TeamID"); + + b.HasIndex("TeamID"); + + b.HasIndex("TeamID", "SolvedTime"); + + b.ToTable("PuzzleStatePerTeam"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PuzzleUser", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("Email") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("EmployeeAlias") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("IdentityUserId") + .IsRequired() + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("IsGlobalAdmin") + .HasColumnType("bit"); + + b.Property("MayBeAdminOrAuthor") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("PhoneNumber") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("TShirtSize") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("VisibleToOthers") + .HasColumnType("bit"); + + b.HasKey("ID"); + + b.HasIndex("IdentityUserId"); + + b.ToTable("PuzzleUsers"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Response", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("IsSolution") + .HasColumnType("bit"); + + b.Property("Note") + .HasColumnType("nvarchar(max)"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("ResponseText") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SubmittedText") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("ID"); + + b.HasIndex("PuzzleID"); + + b.ToTable("Responses"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Room", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("Building") + .HasColumnType("nvarchar(450)"); + + b.Property("Capacity") + .HasColumnType("int"); + + b.Property("CurrentlyOnline") + .HasColumnType("bit"); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("Group") + .HasColumnType("nvarchar(max)"); + + b.Property("Number") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("TeamID"); + + b.HasIndex("EventID", "Building", "Number") + .IsUnique() + .HasFilter("[Building] IS NOT NULL"); + + b.ToTable("Rooms"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleHintStatePerPlayer", b => + { + b.Property("PlayerID") + .HasColumnType("int"); + + b.Property("HintID") + .HasColumnType("int"); + + b.Property("UnlockTime") + .HasColumnType("datetime2"); + + b.HasKey("PlayerID", "HintID"); + + b.HasIndex("HintID"); + + b.ToTable("SinglePlayerPuzzleHintStatePerPlayer"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleStatePerPlayer", b => + { + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("PlayerID") + .HasColumnType("int"); + + b.Property("IsEmailOnlyMode") + .HasColumnType("bit"); + + b.Property("IsHelpThreadUnlockedByCoins") + .HasColumnType("bit"); + + b.Property("LockoutExpiryTime") + .HasColumnType("datetime2"); + + b.Property("Notes") + .HasColumnType("nvarchar(max)"); + + b.Property("Printed") + .HasColumnType("bit"); + + b.Property("SolvedTime") + .HasColumnType("datetime2"); + + b.Property("UnlockedTime") + .HasColumnType("datetime2"); + + b.Property("WrongSubmissionCountBuffer") + .HasColumnType("bigint"); + + b.HasKey("PuzzleID", "PlayerID"); + + b.HasIndex("PlayerID"); + + b.HasIndex("PlayerID", "SolvedTime"); + + b.ToTable("SinglePlayerPuzzleStatePerPlayer"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleSubmission", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AllowFreeformSharing") + .HasColumnType("bit"); + + b.Property("FreeformAccepted") + .HasColumnType("bit"); + + b.Property("FreeformFavorited") + .HasColumnType("bit"); + + b.Property("FreeformJudgeID") + .HasColumnType("int"); + + b.Property("FreeformResponse") + .HasColumnType("nvarchar(max)"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("ResponseID") + .HasColumnType("int"); + + b.Property("SubmissionText") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SubmitterDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("SubmitterID") + .HasColumnType("int"); + + b.Property("TimeSubmitted") + .HasColumnType("datetime2"); + + b.HasKey("ID"); + + b.HasIndex("FreeformJudgeID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("ResponseID"); + + b.HasIndex("SubmitterID", "PuzzleID", "SubmissionText") + .IsUnique(); + + b.ToTable("SinglePlayerPuzzleSubmissions"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleUnlockState", b => + { + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("UnlockedTime") + .HasColumnType("datetime2"); + + b.HasKey("PuzzleID"); + + b.ToTable("SinglePlayerPuzzleUnlockStates"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Submission", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AllowFreeformSharing") + .HasColumnType("bit"); + + b.Property("FreeformAccepted") + .HasColumnType("bit"); + + b.Property("FreeformFavorited") + .HasColumnType("bit"); + + b.Property("FreeformJudgeID") + .HasColumnType("int"); + + b.Property("FreeformResponse") + .HasColumnType("nvarchar(max)"); + + b.Property("PuzzleID") + .HasColumnType("int"); + + b.Property("ResponseID") + .HasColumnType("int"); + + b.Property("SubmissionText") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("SubmitterDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("SubmitterID") + .HasColumnType("int"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.Property("TeamID1") + .HasColumnType("int"); + + b.Property("TimeSubmitted") + .HasColumnType("datetime2"); + + b.HasKey("ID"); + + b.HasIndex("FreeformJudgeID"); + + b.HasIndex("PuzzleID"); + + b.HasIndex("ResponseID"); + + b.HasIndex("SubmitterID"); + + b.HasIndex("TeamID1"); + + b.HasIndex("TeamID", "PuzzleID", "SubmissionText") + .IsUnique(); + + b.ToTable("Submissions"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Team", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("AutoApproveTeammates") + .HasColumnType("bit"); + + b.Property("AutoTeamType") + .HasColumnType("int"); + + b.Property("Bio") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("CustomRoom") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("EventID") + .HasColumnType("int"); + + b.Property("HintCoinCount") + .HasColumnType("int"); + + b.Property("HintCoinsUsed") + .HasColumnType("int"); + + b.Property("IsDisqualified") + .HasColumnType("bit"); + + b.Property("IsLookingForTeammates") + .HasColumnType("bit"); + + b.Property("IsRemoteTeam") + .HasColumnType("bit"); + + b.Property("MergedTeams") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Password") + .HasColumnType("nvarchar(max)"); + + b.Property("PrimaryContactEmail") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("PrimaryPhoneNumber") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("SecondaryPhoneNumber") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("ShowTeamAnnouncement") + .HasColumnType("bit"); + + b.HasKey("ID"); + + b.HasIndex("EventID"); + + b.ToTable("Teams"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamApplication", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("PlayerID") + .HasColumnType("int"); + + b.Property("TeamID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("PlayerID"); + + b.HasIndex("TeamID"); + + b.ToTable("TeamApplications"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamLunch", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("Lunch") + .HasColumnType("nvarchar(max)"); + + b.Property("LunchModifications") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("TeamId") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("TeamId"); + + b.ToTable("TeamLunch"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamMembers", b => + { + b.Property("ID") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("ID")); + + b.Property("ClassID") + .HasColumnType("int"); + + b.Property("MemberID") + .HasColumnType("int") + .HasColumnName("User.ID"); + + b.Property("TeamID") + .HasColumnType("int") + .HasColumnName("Team.ID"); + + b.Property("TemporaryClassID") + .HasColumnType("int"); + + b.HasKey("ID"); + + b.HasIndex("ClassID"); + + b.HasIndex("MemberID"); + + b.HasIndex("TemporaryClassID"); + + b.HasIndex("TeamID", "MemberID"); + + SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("TeamID", "MemberID"), new[] { "ID", "ClassID", "TemporaryClassID" }); + + b.ToTable("TeamMembers"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ServerCore.DataModel.Annotation", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Puzzle"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.ContentFile", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany("Contents") + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Event"); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.EventAdmins", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Admin") + .WithMany() + .HasForeignKey("AdminID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Admin"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("ServerCore.DataModel.EventAuthors", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Author") + .WithMany() + .HasForeignKey("AuthorID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Feedback", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Submitter") + .WithMany() + .HasForeignKey("SubmitterID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Puzzle"); + + b.Navigation("Submitter"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Hint", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.HintStatePerTeam", b => + { + b.HasOne("ServerCore.DataModel.Hint", "Hint") + .WithMany() + .HasForeignKey("HintID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Hint"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Invitation", b => + { + b.HasOne("ServerCore.DataModel.Team", null) + .WithMany("Invitations") + .HasForeignKey("TeamID"); + }); + + modelBuilder.Entity("ServerCore.DataModel.LiveEvent", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "AssociatedPuzzle") + .WithMany() + .HasForeignKey("AssociatedPuzzleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AssociatedPuzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.LiveEventSchedule", b => + { + b.HasOne("ServerCore.DataModel.LiveEvent", "LiveEvent") + .WithMany() + .HasForeignKey("LiveEventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LiveEvent"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Message", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerID") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") + .WithMany() + .HasForeignKey("PlayerID") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Sender") + .WithMany() + .HasForeignKey("SenderID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Claimer"); + + b.Navigation("Event"); + + b.Navigation("Player"); + + b.Navigation("Puzzle"); + + b.Navigation("Sender"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Piece", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PlayerClass", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PlayerInEvent", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") + .WithMany() + .HasForeignKey("PlayerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Event"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Prerequisites", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Prerequisite") + .WithMany() + .HasForeignKey("PrerequisiteID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prerequisite"); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Puzzle", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PuzzleAuthors", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Author") + .WithMany() + .HasForeignKey("AuthorID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.PuzzleStatePerTeam", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Puzzle"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Response", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Room", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID"); + + b.Navigation("Event"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleHintStatePerPlayer", b => + { + b.HasOne("ServerCore.DataModel.Hint", "Hint") + .WithMany() + .HasForeignKey("HintID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") + .WithMany() + .HasForeignKey("PlayerID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Hint"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleStatePerPlayer", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") + .WithMany() + .HasForeignKey("PlayerID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Player"); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleSubmission", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "FreeformJudge") + .WithMany() + .HasForeignKey("FreeformJudgeID"); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany("SinglePlayerPuzzleSubmissions") + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Response", "Response") + .WithMany() + .HasForeignKey("ResponseID"); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Submitter") + .WithMany() + .HasForeignKey("SubmitterID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("FreeformJudge"); + + b.Navigation("Puzzle"); + + b.Navigation("Response"); + + b.Navigation("Submitter"); + }); + + modelBuilder.Entity("ServerCore.DataModel.SinglePlayerPuzzleUnlockState", b => + { + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany() + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Puzzle"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Submission", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "FreeformJudge") + .WithMany() + .HasForeignKey("FreeformJudgeID"); + + b.HasOne("ServerCore.DataModel.Puzzle", "Puzzle") + .WithMany("Submissions") + .HasForeignKey("PuzzleID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Response", "Response") + .WithMany() + .HasForeignKey("ResponseID"); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Submitter") + .WithMany() + .HasForeignKey("SubmitterID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", null) + .WithMany("Submissions") + .HasForeignKey("TeamID1"); + + b.Navigation("FreeformJudge"); + + b.Navigation("Puzzle"); + + b.Navigation("Response"); + + b.Navigation("Submitter"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Team", b => + { + b.HasOne("ServerCore.DataModel.Event", "Event") + .WithMany() + .HasForeignKey("EventID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Event"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamApplication", b => + { + b.HasOne("ServerCore.DataModel.PuzzleUser", "Player") + .WithMany() + .HasForeignKey("PlayerID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Player"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamLunch", b => + { + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("ServerCore.DataModel.TeamMembers", b => + { + b.HasOne("ServerCore.DataModel.PlayerClass", "Class") + .WithMany() + .HasForeignKey("ClassID"); + + b.HasOne("ServerCore.DataModel.PuzzleUser", "Member") + .WithMany() + .HasForeignKey("MemberID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.Team", "Team") + .WithMany() + .HasForeignKey("TeamID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ServerCore.DataModel.PlayerClass", "TemporaryClass") + .WithMany() + .HasForeignKey("TemporaryClassID"); + + b.Navigation("Class"); + + b.Navigation("Member"); + + b.Navigation("Team"); + + b.Navigation("TemporaryClass"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Puzzle", b => + { + b.Navigation("Contents"); + + b.Navigation("SinglePlayerPuzzleSubmissions"); + + b.Navigation("Submissions"); + }); + + modelBuilder.Entity("ServerCore.DataModel.Team", b => + { + b.Navigation("Invitations"); + + b.Navigation("Submissions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Data/Migrations/20260521051857_DbIndexImprovements.cs b/Data/Migrations/20260521051857_DbIndexImprovements.cs new file mode 100644 index 00000000..e95bc0de --- /dev/null +++ b/Data/Migrations/20260521051857_DbIndexImprovements.cs @@ -0,0 +1,167 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Data.Migrations +{ + /// + public partial class DbIndexImprovements : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_TeamMembers_Team.ID", + table: "TeamMembers"); + + migrationBuilder.DropIndex( + name: "IX_Swag_PlayerId", + table: "Swag"); + + migrationBuilder.DropIndex( + name: "IX_Pieces_ProgressLevel", + table: "Pieces"); + + migrationBuilder.DropIndex( + name: "IX_EventAuthors_AuthorID", + table: "EventAuthors"); + + migrationBuilder.DropIndex( + name: "IX_EventAdmins_AdminID", + table: "EventAdmins"); + + migrationBuilder.AlterColumn( + name: "IdentityUserId", + table: "PuzzleUsers", + type: "nvarchar(450)", + maxLength: 450, + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.CreateIndex( + name: "IX_TeamMembers_Team.ID_User.ID", + table: "TeamMembers", + columns: new[] { "Team.ID", "User.ID" }) + .Annotation("SqlServer:Include", new[] { "ID", "ClassID", "TemporaryClassID" }); + + migrationBuilder.CreateIndex( + name: "IX_Swag_PlayerId_EventId", + table: "Swag", + columns: new[] { "PlayerId", "EventId" }); + + migrationBuilder.CreateIndex( + name: "IX_PuzzleUsers_IdentityUserId", + table: "PuzzleUsers", + column: "IdentityUserId"); + + migrationBuilder.CreateIndex( + name: "IX_Puzzles_MinutesOfEventLockout_Availability_ID", + table: "Puzzles", + columns: new[] { "MinutesOfEventLockout", "Availability", "ID" }); + + migrationBuilder.CreateIndex( + name: "IX_Puzzles_MinutesToAutomaticallySolve_Availability_ID", + table: "Puzzles", + columns: new[] { "MinutesToAutomaticallySolve", "Availability", "ID" }); + + migrationBuilder.CreateIndex( + name: "IX_Pieces_ProgressLevel_PuzzleID", + table: "Pieces", + columns: new[] { "ProgressLevel", "PuzzleID" }) + .Annotation("SqlServer:Include", new[] { "ID", "Contents" }); + + migrationBuilder.CreateIndex( + name: "IX_EventAuthors_AuthorID_EventID", + table: "EventAuthors", + columns: new[] { "AuthorID", "EventID" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_EventAdmins_AdminID_EventID", + table: "EventAdmins", + columns: new[] { "AdminID", "EventID" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ContentFiles_EventID_FileType", + table: "ContentFiles", + columns: new[] { "EventID", "FileType" }) + .Annotation("SqlServer:Include", new[] { "ShortName", "UrlString", "PuzzleID" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_TeamMembers_Team.ID_User.ID", + table: "TeamMembers"); + + migrationBuilder.DropIndex( + name: "IX_Swag_PlayerId_EventId", + table: "Swag"); + + migrationBuilder.DropIndex( + name: "IX_PuzzleUsers_IdentityUserId", + table: "PuzzleUsers"); + + migrationBuilder.DropIndex( + name: "IX_Puzzles_MinutesOfEventLockout_Availability_ID", + table: "Puzzles"); + + migrationBuilder.DropIndex( + name: "IX_Puzzles_MinutesToAutomaticallySolve_Availability_ID", + table: "Puzzles"); + + migrationBuilder.DropIndex( + name: "IX_Pieces_ProgressLevel_PuzzleID", + table: "Pieces"); + + migrationBuilder.DropIndex( + name: "IX_EventAuthors_AuthorID_EventID", + table: "EventAuthors"); + + migrationBuilder.DropIndex( + name: "IX_EventAdmins_AdminID_EventID", + table: "EventAdmins"); + + migrationBuilder.DropIndex( + name: "IX_ContentFiles_EventID_FileType", + table: "ContentFiles"); + + migrationBuilder.AlterColumn( + name: "IdentityUserId", + table: "PuzzleUsers", + type: "nvarchar(max)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)", + oldMaxLength: 450); + + migrationBuilder.CreateIndex( + name: "IX_TeamMembers_Team.ID", + table: "TeamMembers", + column: "Team.ID"); + + migrationBuilder.CreateIndex( + name: "IX_Swag_PlayerId", + table: "Swag", + column: "PlayerId"); + + migrationBuilder.CreateIndex( + name: "IX_Pieces_ProgressLevel", + table: "Pieces", + column: "ProgressLevel"); + + migrationBuilder.CreateIndex( + name: "IX_EventAuthors_AuthorID", + table: "EventAuthors", + column: "AuthorID"); + + migrationBuilder.CreateIndex( + name: "IX_EventAdmins_AdminID", + table: "EventAdmins", + column: "AdminID"); + } + } +} diff --git a/Data/Migrations/PuzzleServerContextModelSnapshot.cs b/Data/Migrations/PuzzleServerContextModelSnapshot.cs index a33d239b..d0f811a8 100644 --- a/Data/Migrations/PuzzleServerContextModelSnapshot.cs +++ b/Data/Migrations/PuzzleServerContextModelSnapshot.cs @@ -285,6 +285,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("PuzzleID"); + b.HasIndex("EventID", "FileType"); + + SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("EventID", "FileType"), new[] { "ShortName", "UrlString", "PuzzleID" }); + b.HasIndex("EventID", "ShortName") .IsUnique(); @@ -507,10 +511,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); - b.HasIndex("AdminID"); - b.HasIndex("EventID"); + b.HasIndex("AdminID", "EventID") + .IsUnique(); + b.ToTable("EventAdmins"); }); @@ -530,10 +535,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); - b.HasIndex("AuthorID"); - b.HasIndex("EventID"); + b.HasIndex("AuthorID", "EventID") + .IsUnique(); + b.ToTable("EventAuthors"); }); @@ -828,10 +834,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); - b.HasIndex("ProgressLevel"); - b.HasIndex("PuzzleID"); + b.HasIndex("ProgressLevel", "PuzzleID"); + + SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("ProgressLevel", "PuzzleID"), new[] { "ID", "Contents" }); + b.ToTable("Pieces"); }); @@ -904,7 +912,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventId"); - b.HasIndex("PlayerId"); + b.HasIndex("PlayerId", "EventId"); b.ToTable("Swag"); }); @@ -1059,6 +1067,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("EventID"); + b.HasIndex("MinutesOfEventLockout", "Availability", "ID"); + + b.HasIndex("MinutesToAutomaticallySolve", "Availability", "ID"); + b.ToTable("Puzzles"); }); @@ -1148,7 +1160,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("IdentityUserId") .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); b.Property("IsGlobalAdmin") .HasColumnType("bit"); @@ -1174,6 +1187,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("ID"); + b.HasIndex("IdentityUserId"); + b.ToTable("PuzzleUsers"); }); @@ -1580,24 +1595,28 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("ClassID") .HasColumnType("int"); - b.Property("Team.ID") - .HasColumnType("int"); + b.Property("MemberID") + .HasColumnType("int") + .HasColumnName("User.ID"); - b.Property("TemporaryClassID") - .HasColumnType("int"); + b.Property("TeamID") + .HasColumnType("int") + .HasColumnName("Team.ID"); - b.Property("User.ID") + b.Property("TemporaryClassID") .HasColumnType("int"); b.HasKey("ID"); b.HasIndex("ClassID"); - b.HasIndex("Team.ID"); + b.HasIndex("MemberID"); b.HasIndex("TemporaryClassID"); - b.HasIndex("User.ID"); + b.HasIndex("TeamID", "MemberID"); + + SqlServerIndexBuilderExtensions.IncludeProperties(b.HasIndex("TeamID", "MemberID"), new[] { "ID", "ClassID", "TemporaryClassID" }); b.ToTable("TeamMembers"); }); @@ -2169,9 +2188,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("ClassID"); + b.HasOne("ServerCore.DataModel.PuzzleUser", "Member") + .WithMany() + .HasForeignKey("MemberID") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + b.HasOne("ServerCore.DataModel.Team", "Team") .WithMany() - .HasForeignKey("Team.ID") + .HasForeignKey("TeamID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -2179,12 +2204,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .WithMany() .HasForeignKey("TemporaryClassID"); - b.HasOne("ServerCore.DataModel.PuzzleUser", "Member") - .WithMany() - .HasForeignKey("User.ID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - b.Navigation("Class"); b.Navigation("Member");