f02974b3c2
- Add CmsTrackBrowserViewModel.Invalidate(); called from TrackEdit/BatchEdit on save or delete so album/genre cache is invalidated and re-fetches on next mode switch
- CmsAlbumBrowser now handles 0-track releases: confirm dialog + DeleteReleaseAsync instead of early return; partial-failure path also fires OnReleasesChanged to trigger cache invalidation
- TrackList.OnAlbumsChanged now calls VM.Invalidate() so genres stay fresh after any album delete
- UnifiedTrackService.DeleteAsync cascades release soft-delete when last live track is removed (non-fatal; logs on failure)
- New DELETE api/track/release/{id} endpoint (ApiKeyAuthorize) for direct release soft-delete
- EF migration SoftDeleteOrphanedReleases backfills existing orphaned release rows via raw SQL (data-only, no schema change)
41 lines
1.2 KiB
C#
41 lines
1.2 KiB
C#
using Microsoft.EntityFrameworkCore.Migrations;
|
|
|
|
#nullable disable
|
|
|
|
namespace DeepDrftData.Migrations
|
|
{
|
|
/// <inheritdoc />
|
|
// Data-only migration: no schema change, snapshot unchanged.
|
|
public partial class SoftDeleteOrphanedReleases : Migration
|
|
{
|
|
/// <inheritdoc />
|
|
protected override void Up(MigrationBuilder migrationBuilder)
|
|
{
|
|
// Backfill: soft-delete any live release whose tracks were all soft-deleted before the
|
|
// delete-cascade in UnifiedTrackService existed. These show as 0-track rows in the albums
|
|
// browser; this clears the pre-existing orphans the cascade now prevents going forward.
|
|
migrationBuilder.Sql(@"
|
|
UPDATE release
|
|
SET is_deleted = true,
|
|
updated_at = now()
|
|
WHERE id IN (
|
|
SELECT r.id
|
|
FROM release r
|
|
WHERE r.is_deleted = false
|
|
AND NOT EXISTS (
|
|
SELECT 1
|
|
FROM track t
|
|
WHERE t.release_id = r.id
|
|
AND t.is_deleted = false
|
|
)
|
|
);");
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override void Down(MigrationBuilder migrationBuilder)
|
|
{
|
|
migrationBuilder.Sql("-- no-op: orphaned release soft-deletes are not rolled back");
|
|
}
|
|
}
|
|
}
|