From de86bc3afd0be5cb0ed9fb493652f9b8737cea76 Mon Sep 17 00:00:00 2001
From: Stedoss <29103029+Stedoss@users.noreply.github.com>
Date: Mon, 27 Jul 2026 23:27:47 +0100
Subject: [PATCH] Make mission -> mission launches one-to-many
---
...=> 20260727222052_Add_MissionLaunches.Designer.cs} | 11 +++++------
...nches.cs => 20260727222052_Add_MissionLaunches.cs} | 3 +--
.../Migrations/MissionControlContextModelSnapshot.cs | 9 ++++-----
src/MissionControl.Data/MissionControlContext.cs | 5 +++--
src/MissionControl.Domain/Entities/Mission.cs | 2 +-
.../Endpoints/Missions/Contract.cs | 4 ++--
.../Endpoints/Missions/ListMissions.cs | 2 +-
.../Missions/MissionLaunches/CreateMissionLaunch.cs | 1 -
src/mission-control-client/src/api/missions.ts | 2 +-
9 files changed, 18 insertions(+), 21 deletions(-)
rename src/MissionControl.Data/Migrations/{20260727193151_Add_MissionLaunches.Designer.cs => 20260727222052_Add_MissionLaunches.Designer.cs} (90%)
rename src/MissionControl.Data/Migrations/{20260727193151_Add_MissionLaunches.cs => 20260727222052_Add_MissionLaunches.cs} (96%)
diff --git a/src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.Designer.cs b/src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.Designer.cs
similarity index 90%
rename from src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.Designer.cs
rename to src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.Designer.cs
index e63713d..c065a62 100644
--- a/src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.Designer.cs
+++ b/src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.Designer.cs
@@ -12,7 +12,7 @@ using MissionControl.Data;
namespace MissionControl.Data.Migrations
{
[DbContext(typeof(MissionControlContext))]
- [Migration("20260727193151_Add_MissionLaunches")]
+ [Migration("20260727222052_Add_MissionLaunches")]
partial class Add_MissionLaunches
{
///
@@ -75,8 +75,7 @@ namespace MissionControl.Data.Migrations
b.HasKey("Id");
- b.HasIndex("MissionId")
- .IsUnique();
+ b.HasIndex("MissionId");
b.ToTable("MissionLaunches");
});
@@ -84,8 +83,8 @@ namespace MissionControl.Data.Migrations
modelBuilder.Entity("MissionControl.Domain.Entities.MissionLaunch", b =>
{
b.HasOne("MissionControl.Domain.Entities.Mission", "Mission")
- .WithOne("MissionLaunch")
- .HasForeignKey("MissionControl.Domain.Entities.MissionLaunch", "MissionId")
+ .WithMany("MissionLaunches")
+ .HasForeignKey("MissionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@@ -94,7 +93,7 @@ namespace MissionControl.Data.Migrations
modelBuilder.Entity("MissionControl.Domain.Entities.Mission", b =>
{
- b.Navigation("MissionLaunch");
+ b.Navigation("MissionLaunches");
});
#pragma warning restore 612, 618
}
diff --git a/src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.cs b/src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.cs
similarity index 96%
rename from src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.cs
rename to src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.cs
index da53e03..5e9d5ee 100644
--- a/src/MissionControl.Data/Migrations/20260727193151_Add_MissionLaunches.cs
+++ b/src/MissionControl.Data/Migrations/20260727222052_Add_MissionLaunches.cs
@@ -35,8 +35,7 @@ namespace MissionControl.Data.Migrations
migrationBuilder.CreateIndex(
name: "IX_MissionLaunches_MissionId",
table: "MissionLaunches",
- column: "MissionId",
- unique: true);
+ column: "MissionId");
}
///
diff --git a/src/MissionControl.Data/Migrations/MissionControlContextModelSnapshot.cs b/src/MissionControl.Data/Migrations/MissionControlContextModelSnapshot.cs
index cc18c8c..363de12 100644
--- a/src/MissionControl.Data/Migrations/MissionControlContextModelSnapshot.cs
+++ b/src/MissionControl.Data/Migrations/MissionControlContextModelSnapshot.cs
@@ -72,8 +72,7 @@ namespace MissionControl.Data.Migrations
b.HasKey("Id");
- b.HasIndex("MissionId")
- .IsUnique();
+ b.HasIndex("MissionId");
b.ToTable("MissionLaunches");
});
@@ -81,8 +80,8 @@ namespace MissionControl.Data.Migrations
modelBuilder.Entity("MissionControl.Domain.Entities.MissionLaunch", b =>
{
b.HasOne("MissionControl.Domain.Entities.Mission", "Mission")
- .WithOne("MissionLaunch")
- .HasForeignKey("MissionControl.Domain.Entities.MissionLaunch", "MissionId")
+ .WithMany("MissionLaunches")
+ .HasForeignKey("MissionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@@ -91,7 +90,7 @@ namespace MissionControl.Data.Migrations
modelBuilder.Entity("MissionControl.Domain.Entities.Mission", b =>
{
- b.Navigation("MissionLaunch");
+ b.Navigation("MissionLaunches");
});
#pragma warning restore 612, 618
}
diff --git a/src/MissionControl.Data/MissionControlContext.cs b/src/MissionControl.Data/MissionControlContext.cs
index 4cf14d9..c5637e0 100644
--- a/src/MissionControl.Data/MissionControlContext.cs
+++ b/src/MissionControl.Data/MissionControlContext.cs
@@ -12,9 +12,10 @@ public class MissionControlContext(DbContextOptions optio
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity()
- .HasOne(mission => mission.MissionLaunch)
+ .HasMany(mission => mission.MissionLaunches)
.WithOne(missionLaunch => missionLaunch.Mission)
- .HasForeignKey(missionLaunch => missionLaunch.MissionId);
+ .HasForeignKey(missionLaunch => missionLaunch.MissionId)
+ .IsRequired();
modelBuilder.ApplyConfigurationsFromAssembly(typeof(MissionControlContext).Assembly);
}
diff --git a/src/MissionControl.Domain/Entities/Mission.cs b/src/MissionControl.Domain/Entities/Mission.cs
index 2114f44..99651d9 100644
--- a/src/MissionControl.Domain/Entities/Mission.cs
+++ b/src/MissionControl.Domain/Entities/Mission.cs
@@ -12,5 +12,5 @@ public class Mission
public DateTimeOffset CreatedAt { get; init; } = DateTimeOffset.UtcNow;
- public MissionLaunch? MissionLaunch { get; set; }
+ public ICollection MissionLaunches { get; set; } = new List();
}
diff --git a/src/MissionControl.Server/Endpoints/Missions/Contract.cs b/src/MissionControl.Server/Endpoints/Missions/Contract.cs
index d5f8062..5c6b830 100644
--- a/src/MissionControl.Server/Endpoints/Missions/Contract.cs
+++ b/src/MissionControl.Server/Endpoints/Missions/Contract.cs
@@ -15,7 +15,7 @@ public record MissionResponse
public required DateTimeOffset CreatedAt { get; init; }
- public MissionLaunchResponse? MissionLaunch { get; set; }
+ public IReadOnlyList MissionLaunches { get; set; } = [];
public static MissionResponse FromDomain(Mission mission) =>
new()
@@ -25,6 +25,6 @@ public record MissionResponse
Description = mission.Description,
Status = mission.Status,
CreatedAt = mission.CreatedAt,
- MissionLaunch = mission.MissionLaunch != null ? MissionLaunchResponse.FromDomain(mission.MissionLaunch) : null,
+ MissionLaunches = mission.MissionLaunches.Select(MissionLaunchResponse.FromDomain).ToList(),
};
}
diff --git a/src/MissionControl.Server/Endpoints/Missions/ListMissions.cs b/src/MissionControl.Server/Endpoints/Missions/ListMissions.cs
index ef20adb..b07c3dd 100644
--- a/src/MissionControl.Server/Endpoints/Missions/ListMissions.cs
+++ b/src/MissionControl.Server/Endpoints/Missions/ListMissions.cs
@@ -16,7 +16,7 @@ public class ListMissions(MissionControlContext dbContext)
{
var missions = await dbContext.Missions
.AsNoTracking()
- .Include(m => m.MissionLaunch)
+ .Include(m => m.MissionLaunches)
.OrderByDescending(m => m.CreatedAt)
.ToListAsync(ct);
diff --git a/src/MissionControl.Server/Endpoints/Missions/MissionLaunches/CreateMissionLaunch.cs b/src/MissionControl.Server/Endpoints/Missions/MissionLaunches/CreateMissionLaunch.cs
index 29bcd9c..fa66805 100644
--- a/src/MissionControl.Server/Endpoints/Missions/MissionLaunches/CreateMissionLaunch.cs
+++ b/src/MissionControl.Server/Endpoints/Missions/MissionLaunches/CreateMissionLaunch.cs
@@ -1,6 +1,5 @@
using FastEndpoints;
using FluentValidation;
-using Microsoft.AspNetCore.Mvc;
using MissionControl.Data;
using MissionControl.Domain.Entities;
diff --git a/src/mission-control-client/src/api/missions.ts b/src/mission-control-client/src/api/missions.ts
index 542db50..4cc1632 100644
--- a/src/mission-control-client/src/api/missions.ts
+++ b/src/mission-control-client/src/api/missions.ts
@@ -9,7 +9,7 @@ export type Mission = {
description: string | null;
status: MissionStatus;
createdAt: string;
- missionLaunch: MissionLaunch | null;
+ missionLaunches: MissionLaunch[];
};
export type CreateMissionRequest = {