using Microsoft.EntityFrameworkCore.Migrations; #nullable disable namespace DeepDrftData.Migrations { /// public partial class AddReleaseEntryKey : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) { // 11.H — front the int PK with an app-minted GUID-string EntryKey (Phase 11 §3e). The // scaffolded single non-null-with-"" add is hand-edited into the three-step backfill the // spec requires (§3e.5(2)): existing rows must each get a UNIQUE, non-null key, so a shared // "" default would collide on the unique index. Add nullable → backfill a GUID per row → // mark non-null. No DB default is set on the final column: new rows are app-populated by // FindOrCreateRelease (Guid.NewGuid().ToString()), exactly as tracks mint their EntryKey. // 1) Add the column nullable so the backfill can run before the NOT NULL constraint. migrationBuilder.AddColumn( name: "entry_key", table: "release", type: "character varying(100)", maxLength: 100, nullable: true); // 2) Backfill a unique GUID string per existing row. gen_random_uuid()::text yields the // lowercase 36-char hyphenated shape Guid.NewGuid().ToString() produces, so migrated and // app-minted keys are indistinguishable. Per-row evaluation → each row gets a distinct key. migrationBuilder.Sql( "UPDATE \"release\" SET \"entry_key\" = gen_random_uuid()::text WHERE \"entry_key\" IS NULL;"); // 3) Now every row is populated and unique — enforce NOT NULL. migrationBuilder.AlterColumn( name: "entry_key", table: "release", type: "character varying(100)", maxLength: 100, nullable: false, oldClrType: typeof(string), oldType: "character varying(100)", oldMaxLength: 100, oldNullable: true); migrationBuilder.CreateIndex( name: "IX_release_entry_key", table: "release", column: "entry_key", unique: true); } /// protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropIndex( name: "IX_release_entry_key", table: "release"); migrationBuilder.DropColumn( name: "entry_key", table: "release"); } } }