Add EventOccurrence entity and update DbContext

Created the EventOccurrence entity with properties for event details and added it to the AppDbContext. Updated the model snapshot to reflect the new entity and its relationships, ensuring proper database schema generation.
This commit is contained in:
2025-12-27 15:59:48 -05:00
parent eaefdfaedd
commit 3a809f18a6
6 changed files with 522 additions and 3 deletions
+11 -3
View File
@@ -1,14 +1,22 @@
namespace Core.Entities
namespace Core.Entities
{ {
public class EventOccurrence public class EventOccurrence
{ {
public int Id { get; set; }
public int? EventDefinitionId { get; set; }
public string? SpecialEventType { get; set; }
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
public string Time { get; set; } = null!; public string Time { get; set; } = null!;
public string Date { get; set; } = null!; public string Date { get; set; } = null!;
public DateTime StartTime { get; set; } public DateTime StartTime { get; set; }
public DateTime? EndTime { get; set; } public DateTime? EndTime { get; set; }
public string Location { get; set; } = null!; public string? Location { get; set; }
// Navigation property
public EventDefinition? EventDefinition { get; set; }
public bool SignupSubmitPickup => public bool SignupSubmitPickup =>
Name.Contains("Sign-up") || Name.Contains("Sign-up") ||
+1
View File
@@ -10,6 +10,7 @@ namespace Data
public DbSet<Student> Students { get; set; } public DbSet<Student> Students { get; set; }
public DbSet<Team> Teams { get; set; } public DbSet<Team> Teams { get; set; }
public DbSet<StudentEventRanking> StudentEventRanking { get; set; } public DbSet<StudentEventRanking> StudentEventRanking { get; set; }
public DbSet<EventOccurrence> EventOccurrences { get; set; }
public AppDbContext() public AppDbContext()
{ {
@@ -0,0 +1,48 @@
using Core.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Data.Configurations
{
public class EventOccurrenceConfiguration : IEntityTypeConfiguration<EventOccurrence>
{
public void Configure(EntityTypeBuilder<EventOccurrence> builder)
{
builder.HasKey(e => e.Id);
// Indexes
builder.HasIndex(e => e.StartTime);
builder.HasIndex(e => e.EventDefinitionId);
builder.HasIndex(e => e.SpecialEventType);
// Foreign key relationship (optional)
builder.HasOne(e => e.EventDefinition)
.WithMany()
.HasForeignKey(e => e.EventDefinitionId)
.OnDelete(DeleteBehavior.Restrict); // Don't cascade delete if EventDefinition is deleted
// Constraints
builder.Property(e => e.Name)
.IsRequired()
.HasMaxLength(200);
builder.Property(e => e.Time)
.IsRequired()
.HasMaxLength(100);
builder.Property(e => e.Date)
.IsRequired()
.HasMaxLength(100);
builder.Property(e => e.Location)
.HasMaxLength(500);
builder.Property(e => e.SpecialEventType)
.HasMaxLength(50);
// Validation: Either EventDefinitionId OR SpecialEventType must be set (enforced at application level)
// EF Core doesn't support mutually exclusive constraints directly, so we'll handle this in validation attributes or service layer
}
}
}
+339
View File
@@ -0,0 +1,339 @@
// <auto-generated />
using System;
using Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Data.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20251227205816_EventOccurrence")]
partial class EventOccurrence
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.8");
modelBuilder.Entity("Core.Entities.EventDefinition", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("ChapterEligibilityCountRegionals")
.HasColumnType("INTEGER");
b.Property<int>("ChapterEligibilityCountState")
.HasColumnType("INTEGER");
b.Property<string>("Description")
.HasMaxLength(1000)
.HasColumnType("TEXT");
b.Property<string>("Documentation")
.HasMaxLength(500)
.HasColumnType("TEXT");
b.Property<string>("Eligibility")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("TEXT");
b.Property<string>("EventFormat")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<int?>("LevelOfEffort")
.HasColumnType("INTEGER");
b.Property<int>("MaxTeamSize")
.HasColumnType("INTEGER");
b.Property<int>("MinTeamSize")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("TEXT");
b.Property<string>("Notes")
.HasMaxLength(1024)
.HasColumnType("TEXT");
b.Property<bool>("OnSiteActivity")
.HasColumnType("INTEGER");
b.Property<bool>("Presubmission")
.HasColumnType("INTEGER");
b.Property<string>("SemifinalistActivity")
.HasMaxLength(500)
.HasColumnType("TEXT");
b.Property<string>("ShortName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("Theme")
.HasMaxLength(500)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("EventFormat");
b.HasIndex("Name")
.IsUnique();
b.ToTable("Events");
});
modelBuilder.Entity("Core.Entities.EventOccurrence", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Date")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<DateTime?>("EndTime")
.HasColumnType("TEXT");
b.Property<int?>("EventDefinitionId")
.HasColumnType("INTEGER");
b.Property<string>("Location")
.HasMaxLength(500)
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("TEXT");
b.Property<string>("SpecialEventType")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime>("StartTime")
.HasColumnType("TEXT");
b.Property<string>("Time")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("EventDefinitionId");
b.HasIndex("SpecialEventType");
b.HasIndex("StartTime");
b.ToTable("EventOccurrences");
});
modelBuilder.Entity("Core.Entities.Student", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Email")
.HasMaxLength(255)
.HasColumnType("TEXT");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<int>("Grade")
.HasColumnType("INTEGER");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<string>("NationalId")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("OfficerRole")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("PhoneNumber")
.HasMaxLength(20)
.HasColumnType("TEXT");
b.Property<string>("RegionalId")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("StateId")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<int>("TsaYear")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("Email");
b.HasIndex("Grade");
b.HasIndex("FirstName", "LastName");
b.ToTable("Students");
});
modelBuilder.Entity("Core.Entities.StudentEventRanking", b =>
{
b.Property<int>("StudentId")
.HasColumnType("INTEGER");
b.Property<int>("EventDefinitionId")
.HasColumnType("INTEGER");
b.Property<int>("Rank")
.HasColumnType("INTEGER");
b.HasKey("StudentId", "EventDefinitionId");
b.HasIndex("EventDefinitionId");
b.HasIndex("Rank");
b.HasIndex("StudentId");
b.ToTable("StudentEventRanking");
});
modelBuilder.Entity("Core.Entities.Team", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int?>("CaptainId")
.HasColumnType("INTEGER");
b.Property<int>("EventId")
.HasColumnType("INTEGER");
b.Property<string>("Identifier")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("CaptainId");
b.HasIndex("EventId");
b.HasIndex("EventId", "Identifier");
b.ToTable("Teams");
});
modelBuilder.Entity("StudentTeam", b =>
{
b.Property<int>("StudentsId")
.HasColumnType("INTEGER");
b.Property<int>("TeamsId")
.HasColumnType("INTEGER");
b.HasKey("StudentsId", "TeamsId");
b.HasIndex("TeamsId");
b.ToTable("TeamStudents", (string)null);
});
modelBuilder.Entity("Core.Entities.EventOccurrence", b =>
{
b.HasOne("Core.Entities.EventDefinition", "EventDefinition")
.WithMany()
.HasForeignKey("EventDefinitionId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("EventDefinition");
});
modelBuilder.Entity("Core.Entities.StudentEventRanking", b =>
{
b.HasOne("Core.Entities.EventDefinition", "EventDefinition")
.WithMany()
.HasForeignKey("EventDefinitionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Core.Entities.Student", "Student")
.WithMany("EventRankings")
.HasForeignKey("StudentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("EventDefinition");
b.Navigation("Student");
});
modelBuilder.Entity("Core.Entities.Team", b =>
{
b.HasOne("Core.Entities.Student", "Captain")
.WithMany()
.HasForeignKey("CaptainId")
.OnDelete(DeleteBehavior.SetNull);
b.HasOne("Core.Entities.EventDefinition", "Event")
.WithMany()
.HasForeignKey("EventId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Captain");
b.Navigation("Event");
});
modelBuilder.Entity("StudentTeam", b =>
{
b.HasOne("Core.Entities.Student", null)
.WithMany()
.HasForeignKey("StudentsId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Core.Entities.Team", null)
.WithMany()
.HasForeignKey("TeamsId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Core.Entities.Student", b =>
{
b.Navigation("EventRankings");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,63 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Data.Migrations
{
/// <inheritdoc />
public partial class EventOccurrence : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "EventOccurrences",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
EventDefinitionId = table.Column<int>(type: "INTEGER", nullable: true),
SpecialEventType = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
Name = table.Column<string>(type: "TEXT", maxLength: 200, nullable: false),
Time = table.Column<string>(type: "TEXT", maxLength: 100, nullable: false),
Date = table.Column<string>(type: "TEXT", maxLength: 100, nullable: false),
StartTime = table.Column<DateTime>(type: "TEXT", nullable: false),
EndTime = table.Column<DateTime>(type: "TEXT", nullable: true),
Location = table.Column<string>(type: "TEXT", maxLength: 500, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_EventOccurrences", x => x.Id);
table.ForeignKey(
name: "FK_EventOccurrences_Events_EventDefinitionId",
column: x => x.EventDefinitionId,
principalTable: "Events",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_EventOccurrences_EventDefinitionId",
table: "EventOccurrences",
column: "EventDefinitionId");
migrationBuilder.CreateIndex(
name: "IX_EventOccurrences_SpecialEventType",
table: "EventOccurrences",
column: "SpecialEventType");
migrationBuilder.CreateIndex(
name: "IX_EventOccurrences_StartTime",
table: "EventOccurrences",
column: "StartTime");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "EventOccurrences");
}
}
}
@@ -1,4 +1,5 @@
// <auto-generated /> // <auto-generated />
using System;
using Data; using Data;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -93,6 +94,55 @@ namespace Data.Migrations
b.ToTable("Events"); b.ToTable("Events");
}); });
modelBuilder.Entity("Core.Entities.EventOccurrence", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Date")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<DateTime?>("EndTime")
.HasColumnType("TEXT");
b.Property<int?>("EventDefinitionId")
.HasColumnType("INTEGER");
b.Property<string>("Location")
.HasMaxLength(500)
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("TEXT");
b.Property<string>("SpecialEventType")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime>("StartTime")
.HasColumnType("TEXT");
b.Property<string>("Time")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("EventDefinitionId");
b.HasIndex("SpecialEventType");
b.HasIndex("StartTime");
b.ToTable("EventOccurrences");
});
modelBuilder.Entity("Core.Entities.Student", b => modelBuilder.Entity("Core.Entities.Student", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@@ -214,6 +264,16 @@ namespace Data.Migrations
b.ToTable("TeamStudents", (string)null); b.ToTable("TeamStudents", (string)null);
}); });
modelBuilder.Entity("Core.Entities.EventOccurrence", b =>
{
b.HasOne("Core.Entities.EventDefinition", "EventDefinition")
.WithMany()
.HasForeignKey("EventDefinitionId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("EventDefinition");
});
modelBuilder.Entity("Core.Entities.StudentEventRanking", b => modelBuilder.Entity("Core.Entities.StudentEventRanking", b =>
{ {
b.HasOne("Core.Entities.EventDefinition", "EventDefinition") b.HasOne("Core.Entities.EventDefinition", "EventDefinition")