From b3612f5bec5ea8968bc1883f9b2c7d7a65ea6092 Mon Sep 17 00:00:00 2001 From: timothe Date: Wed, 27 May 2026 20:32:55 +0200 Subject: [PATCH] Remove /api prefix from all routes and fix CityId FK constraint - Strip /api prefix from all endpoint routes - Make Show.CityId nullable (no longer required FK) - Drop CityId FK constraint and alter column to NULL at startup via raw SQL - Add migration MakeCityIdNullable for schema consistency - Update Show DTOs to reflect nullable CityId Co-Authored-By: Claude Sonnet 4.6 --- PyroFetes/DTO/Show/Request/CreateShowDto.cs | 2 +- PyroFetes/DTO/Show/Response/ReadShowDto.cs | 2 +- .../Endpoints/Show/CreateShowEndpoint.cs | 2 +- .../Endpoints/Show/DeleteShowEndpoint.cs | 2 +- .../Endpoints/Show/GetAllShowsEndpoint.cs | 2 +- PyroFetes/Endpoints/Show/GetShowEndpoint.cs | 2 +- .../Endpoints/Show/UpdateShowEndpoint.cs | 2 +- .../Endpoints/Sound/CreateSoundEndpoint.cs | 2 +- .../Endpoints/Sound/DeleteSoundEndpoint.cs | 2 +- .../Endpoints/Sound/GetAllSoundsEndpoint.cs | 2 +- PyroFetes/Endpoints/Sound/GetSoundEndpoint.cs | 2 +- .../Endpoints/Sound/UpdateSoundEndpoint.cs | 2 +- .../CreateSoundCategoryEndpoint.cs | 2 +- .../DeleteSoundCategoryEndpoint.cs | 2 +- .../GetAllSoundCategoryEndpoint.cs | 2 +- .../SoundCategory/GetSoundCategoryEndpoint.cs | 2 +- .../UpdateSoundCategoryEndpoint.cs | 2 +- .../CreateSoundTimecodeEndpoint.cs | 2 +- .../DeleteSoundTimecodeEndpoint.cs | 2 +- .../GetAllSoundTimecodesEndpoint.cs | 2 +- .../SoundTimecode/GetSoundTimecodeEndpoint.cs | 2 +- .../UpdateSoundTimecodeEndpoint.cs | 2 +- .../Endpoints/Staff/CreateStaffEndpoint.cs | 2 +- .../Endpoints/Staff/DeleteStaffEndpoint.cs | 2 +- .../Endpoints/Staff/GetAllStaffEndpoint.cs | 2 +- PyroFetes/Endpoints/Staff/GetStaffEndpoint.cs | 2 +- .../Endpoints/Staff/UpdateStaffEndpoint.cs | 2 +- .../Endpoints/Truck/CreateTruckEndpoint.cs | 2 +- .../Endpoints/Truck/DeleteTruckEndpoint.cs | 2 +- .../Endpoints/Truck/GetAllTrucksEndpoint.cs | 2 +- PyroFetes/Endpoints/Truck/GetTruckEndpoint.cs | 2 +- .../Endpoints/Truck/UpdateTruckEndpoint.cs | 2 +- .../20260527000000_MakeCityIdNullable.cs | 59 +++++++++++++++++++ .../PyroFetesDbContextModelSnapshot.cs | 5 +- PyroFetes/Models/Show.cs | 2 +- PyroFetes/Program.cs | 17 ++++++ 36 files changed, 111 insertions(+), 36 deletions(-) create mode 100644 PyroFetes/Migrations/20260527000000_MakeCityIdNullable.cs diff --git a/PyroFetes/DTO/Show/Request/CreateShowDto.cs b/PyroFetes/DTO/Show/Request/CreateShowDto.cs index 05e62b7..32a4d45 100644 --- a/PyroFetes/DTO/Show/Request/CreateShowDto.cs +++ b/PyroFetes/DTO/Show/Request/CreateShowDto.cs @@ -7,5 +7,5 @@ public class CreateShowDto public string? Description { get; set; } public string? PyrotechnicImplementationPlan { get; set; } public DateTime? Date { get; set; } - public int CityId { get; set; } + public int? CityId { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/Show/Response/ReadShowDto.cs b/PyroFetes/DTO/Show/Response/ReadShowDto.cs index c9a6250..d9e7d13 100644 --- a/PyroFetes/DTO/Show/Response/ReadShowDto.cs +++ b/PyroFetes/DTO/Show/Response/ReadShowDto.cs @@ -8,5 +8,5 @@ public class ReadShowDto public string? Description { get; set; } public string? PyrotechnicImplementationPlan { get; set; } public DateTime? Date { get; set; } - public int CityId { get; set; } + public int? CityId { get; set; } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Show/CreateShowEndpoint.cs b/PyroFetes/Endpoints/Show/CreateShowEndpoint.cs index d3b2133..4c78ae1 100644 --- a/PyroFetes/Endpoints/Show/CreateShowEndpoint.cs +++ b/PyroFetes/Endpoints/Show/CreateShowEndpoint.cs @@ -8,7 +8,7 @@ public class CreateShowEndpoint(PyroFetesDbContext pyroFetesDbContext) : Endpoin { public override void Configure() { - Post("/api/shows"); + Post("/shows"); AllowAnonymous(); } diff --git a/PyroFetes/Endpoints/Show/DeleteShowEndpoint.cs b/PyroFetes/Endpoints/Show/DeleteShowEndpoint.cs index d31723c..33c9b96 100644 --- a/PyroFetes/Endpoints/Show/DeleteShowEndpoint.cs +++ b/PyroFetes/Endpoints/Show/DeleteShowEndpoint.cs @@ -8,7 +8,7 @@ public class DeleteShowEndpoint(PyroFetesDbContext pyroFetesDbContext) : Endpoin { public override void Configure() { - Delete("/api/shows/{Id}"); + Delete("/shows/{Id}"); AllowAnonymous(); } diff --git a/PyroFetes/Endpoints/Show/GetAllShowsEndpoint.cs b/PyroFetes/Endpoints/Show/GetAllShowsEndpoint.cs index 111a87c..df2034f 100644 --- a/PyroFetes/Endpoints/Show/GetAllShowsEndpoint.cs +++ b/PyroFetes/Endpoints/Show/GetAllShowsEndpoint.cs @@ -8,7 +8,7 @@ public class GetAllShowsEndpoint(PyroFetesDbContext pyroFetesDbContext) : Endpoi { public override void Configure() { - Get("/api/shows"); + Get("/shows"); AllowAnonymous(); } diff --git a/PyroFetes/Endpoints/Show/GetShowEndpoint.cs b/PyroFetes/Endpoints/Show/GetShowEndpoint.cs index ab11d04..e4d1e8e 100644 --- a/PyroFetes/Endpoints/Show/GetShowEndpoint.cs +++ b/PyroFetes/Endpoints/Show/GetShowEndpoint.cs @@ -9,7 +9,7 @@ public class GetShowEndpoint(PyroFetesDbContext pyroFetesDbContext) : Endpoint + public partial class MakeCityIdNullable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Shows_Cities_CityId", + table: "Shows"); + + migrationBuilder.AlterColumn( + name: "CityId", + table: "Shows", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AddForeignKey( + name: "FK_Shows_Cities_CityId", + table: "Shows", + column: "CityId", + principalTable: "Cities", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Shows_Cities_CityId", + table: "Shows"); + + migrationBuilder.AlterColumn( + name: "CityId", + table: "Shows", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_Shows_Cities_CityId", + table: "Shows", + column: "CityId", + principalTable: "Cities", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/PyroFetes/Migrations/PyroFetesDbContextModelSnapshot.cs b/PyroFetes/Migrations/PyroFetesDbContextModelSnapshot.cs index 1f414fb..6b8e23a 100644 --- a/PyroFetes/Migrations/PyroFetesDbContextModelSnapshot.cs +++ b/PyroFetes/Migrations/PyroFetesDbContextModelSnapshot.cs @@ -813,7 +813,7 @@ namespace PyroFetes.Migrations SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - b.Property("CityId") + b.Property("CityId") .HasColumnType("int"); b.Property("Date") @@ -1594,8 +1594,7 @@ namespace PyroFetes.Migrations b.HasOne("PyroFetes.Models.City", "City") .WithMany("Shows") .HasForeignKey("CityId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .OnDelete(DeleteBehavior.ClientSetNull); b.Navigation("City"); }); diff --git a/PyroFetes/Models/Show.cs b/PyroFetes/Models/Show.cs index bc425dd..c8e3014 100644 --- a/PyroFetes/Models/Show.cs +++ b/PyroFetes/Models/Show.cs @@ -13,7 +13,7 @@ public class Show // Link (path/URL/file name) to the pyrotechnic implementation plan [Required, MaxLength(500)] public string? PyrotechnicImplementationPlan { get; set; } - [Required] public int CityId { get; set; } + public int? CityId { get; set; } public City? City { get; set; } public List? ShowStaffs { get; set; } diff --git a/PyroFetes/Program.cs b/PyroFetes/Program.cs index 7c63bff..b95d325 100644 --- a/PyroFetes/Program.cs +++ b/PyroFetes/Program.cs @@ -13,6 +13,23 @@ builder.Services.SwaggerDocument(); var app = builder.Build(); +using (var scope = app.Services.CreateScope()) +{ + var db = scope.ServiceProvider.GetRequiredService(); + db.Database.ExecuteSqlRaw(""" + IF EXISTS ( + SELECT 1 FROM sys.foreign_keys + WHERE name = 'FK_Shows_Cities_CityId' AND parent_object_id = OBJECT_ID('Shows') + ) + ALTER TABLE Shows DROP CONSTRAINT FK_Shows_Cities_CityId + """); + db.Database.ExecuteSqlRaw(""" + IF COL_LENGTH('Shows', 'CityId') IS NOT NULL + AND COLUMNPROPERTY(OBJECT_ID('Shows'), 'CityId', 'AllowsNull') = 0 + ALTER TABLE Shows ALTER COLUMN CityId INT NULL + """); +} + if (app.Environment.IsDevelopment()) { app.UseSwaggerGen();