Make mission -> mission launches one-to-many

This commit is contained in:
Stedoss
2026-07-27 23:27:47 +01:00
parent 2d5c795a07
commit de86bc3afd
9 changed files with 18 additions and 21 deletions
@@ -12,7 +12,7 @@ using MissionControl.Data;
namespace MissionControl.Data.Migrations namespace MissionControl.Data.Migrations
{ {
[DbContext(typeof(MissionControlContext))] [DbContext(typeof(MissionControlContext))]
[Migration("20260727193151_Add_MissionLaunches")] [Migration("20260727222052_Add_MissionLaunches")]
partial class Add_MissionLaunches partial class Add_MissionLaunches
{ {
/// <inheritdoc /> /// <inheritdoc />
@@ -75,8 +75,7 @@ namespace MissionControl.Data.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("MissionId") b.HasIndex("MissionId");
.IsUnique();
b.ToTable("MissionLaunches"); b.ToTable("MissionLaunches");
}); });
@@ -84,8 +83,8 @@ namespace MissionControl.Data.Migrations
modelBuilder.Entity("MissionControl.Domain.Entities.MissionLaunch", b => modelBuilder.Entity("MissionControl.Domain.Entities.MissionLaunch", b =>
{ {
b.HasOne("MissionControl.Domain.Entities.Mission", "Mission") b.HasOne("MissionControl.Domain.Entities.Mission", "Mission")
.WithOne("MissionLaunch") .WithMany("MissionLaunches")
.HasForeignKey("MissionControl.Domain.Entities.MissionLaunch", "MissionId") .HasForeignKey("MissionId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
@@ -94,7 +93,7 @@ namespace MissionControl.Data.Migrations
modelBuilder.Entity("MissionControl.Domain.Entities.Mission", b => modelBuilder.Entity("MissionControl.Domain.Entities.Mission", b =>
{ {
b.Navigation("MissionLaunch"); b.Navigation("MissionLaunches");
}); });
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
@@ -35,8 +35,7 @@ namespace MissionControl.Data.Migrations
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_MissionLaunches_MissionId", name: "IX_MissionLaunches_MissionId",
table: "MissionLaunches", table: "MissionLaunches",
column: "MissionId", column: "MissionId");
unique: true);
} }
/// <inheritdoc /> /// <inheritdoc />
@@ -72,8 +72,7 @@ namespace MissionControl.Data.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("MissionId") b.HasIndex("MissionId");
.IsUnique();
b.ToTable("MissionLaunches"); b.ToTable("MissionLaunches");
}); });
@@ -81,8 +80,8 @@ namespace MissionControl.Data.Migrations
modelBuilder.Entity("MissionControl.Domain.Entities.MissionLaunch", b => modelBuilder.Entity("MissionControl.Domain.Entities.MissionLaunch", b =>
{ {
b.HasOne("MissionControl.Domain.Entities.Mission", "Mission") b.HasOne("MissionControl.Domain.Entities.Mission", "Mission")
.WithOne("MissionLaunch") .WithMany("MissionLaunches")
.HasForeignKey("MissionControl.Domain.Entities.MissionLaunch", "MissionId") .HasForeignKey("MissionId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
@@ -91,7 +90,7 @@ namespace MissionControl.Data.Migrations
modelBuilder.Entity("MissionControl.Domain.Entities.Mission", b => modelBuilder.Entity("MissionControl.Domain.Entities.Mission", b =>
{ {
b.Navigation("MissionLaunch"); b.Navigation("MissionLaunches");
}); });
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
@@ -12,9 +12,10 @@ public class MissionControlContext(DbContextOptions<MissionControlContext> optio
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
modelBuilder.Entity<Mission>() modelBuilder.Entity<Mission>()
.HasOne(mission => mission.MissionLaunch) .HasMany(mission => mission.MissionLaunches)
.WithOne(missionLaunch => missionLaunch.Mission) .WithOne(missionLaunch => missionLaunch.Mission)
.HasForeignKey<MissionLaunch>(missionLaunch => missionLaunch.MissionId); .HasForeignKey(missionLaunch => missionLaunch.MissionId)
.IsRequired();
modelBuilder.ApplyConfigurationsFromAssembly(typeof(MissionControlContext).Assembly); modelBuilder.ApplyConfigurationsFromAssembly(typeof(MissionControlContext).Assembly);
} }
@@ -12,5 +12,5 @@ public class Mission
public DateTimeOffset CreatedAt { get; init; } = DateTimeOffset.UtcNow; public DateTimeOffset CreatedAt { get; init; } = DateTimeOffset.UtcNow;
public MissionLaunch? MissionLaunch { get; set; } public ICollection<MissionLaunch> MissionLaunches { get; set; } = new List<MissionLaunch>();
} }
@@ -15,7 +15,7 @@ public record MissionResponse
public required DateTimeOffset CreatedAt { get; init; } public required DateTimeOffset CreatedAt { get; init; }
public MissionLaunchResponse? MissionLaunch { get; set; } public IReadOnlyList<MissionLaunchResponse> MissionLaunches { get; set; } = [];
public static MissionResponse FromDomain(Mission mission) => public static MissionResponse FromDomain(Mission mission) =>
new() new()
@@ -25,6 +25,6 @@ public record MissionResponse
Description = mission.Description, Description = mission.Description,
Status = mission.Status, Status = mission.Status,
CreatedAt = mission.CreatedAt, CreatedAt = mission.CreatedAt,
MissionLaunch = mission.MissionLaunch != null ? MissionLaunchResponse.FromDomain(mission.MissionLaunch) : null, MissionLaunches = mission.MissionLaunches.Select(MissionLaunchResponse.FromDomain).ToList(),
}; };
} }
@@ -16,7 +16,7 @@ public class ListMissions(MissionControlContext dbContext)
{ {
var missions = await dbContext.Missions var missions = await dbContext.Missions
.AsNoTracking() .AsNoTracking()
.Include(m => m.MissionLaunch) .Include(m => m.MissionLaunches)
.OrderByDescending(m => m.CreatedAt) .OrderByDescending(m => m.CreatedAt)
.ToListAsync(ct); .ToListAsync(ct);
@@ -1,6 +1,5 @@
using FastEndpoints; using FastEndpoints;
using FluentValidation; using FluentValidation;
using Microsoft.AspNetCore.Mvc;
using MissionControl.Data; using MissionControl.Data;
using MissionControl.Domain.Entities; using MissionControl.Domain.Entities;
@@ -9,7 +9,7 @@ export type Mission = {
description: string | null; description: string | null;
status: MissionStatus; status: MissionStatus;
createdAt: string; createdAt: string;
missionLaunch: MissionLaunch | null; missionLaunches: MissionLaunch[];
}; };
export type CreateMissionRequest = { export type CreateMissionRequest = {