From 3439d3c017a06604e7b471a1063a8467306f78f2 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Sun, 15 Feb 2026 23:12:52 +0100 Subject: [PATCH] Migrate PrimaryVersionId to GUID and fix assignment --- .../Library/LibraryManager.cs | 11 +- Jellyfin.Api/Controllers/VideosController.cs | 8 +- .../FixIncorrectOwnerIdRelationships.cs | 4 +- .../Migrations/Routines/MigrateLibraryDb.cs | 4 +- MediaBrowser.Controller/Entities/Folder.cs | 2 +- MediaBrowser.Controller/Entities/Video.cs | 34 +- .../Entities/BaseItemEntity.cs | 2 +- ...4_ChangePrimaryVersionIdToGuid.Designer.cs | 1791 +++++++++++++++++ ...0215201634_ChangePrimaryVersionIdToGuid.cs | 54 + .../Migrations/JellyfinDbModelSnapshot.cs | 4 +- 10 files changed, 1880 insertions(+), 34 deletions(-) create mode 100644 src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20260215201634_ChangePrimaryVersionIdToGuid.Designer.cs create mode 100644 src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20260215201634_ChangePrimaryVersionIdToGuid.cs diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index df259c303f..7517dc03ba 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -408,7 +408,7 @@ namespace Emby.Server.Implementations.Library // If deleting a primary version video, clear PrimaryVersionId from alternate versions // OwnerId check: items with OwnerId set are alternate versions or extras, not primaries - if (item is Video video && string.IsNullOrEmpty(video.PrimaryVersionId) && video.OwnerId.IsEmpty()) + if (item is Video video && !video.PrimaryVersionId.HasValue && video.OwnerId.IsEmpty()) { var alternateVersions = GetLocalAlternateVersionIds(video) .Concat(GetLinkedAlternateVersions(video).Select(v => v.Id)) @@ -435,16 +435,15 @@ namespace Emby.Server.Implementations.Library // Update remaining alternates to point to new primary foreach (var alternate in alternateVersions.Skip(1)) { - alternate.SetPrimaryVersionId(newPrimary.Id.ToString("N", CultureInfo.InvariantCulture)); + alternate.SetPrimaryVersionId(newPrimary.Id); alternate.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter().GetResult(); } } } - else if (item is Video alternateVideo && !string.IsNullOrEmpty(alternateVideo.PrimaryVersionId) - && Guid.TryParse(alternateVideo.PrimaryVersionId, out var primaryId)) + else if (item is Video alternateVideo && alternateVideo.PrimaryVersionId.HasValue) { // If deleting an alternate version, re-route references to its primary - _itemRepository.RerouteLinkedChildren(alternateVideo.Id, primaryId); + _itemRepository.RerouteLinkedChildren(alternateVideo.Id, alternateVideo.PrimaryVersionId.Value); } var children = item.IsFolder @@ -2181,6 +2180,7 @@ namespace Emby.Server.Implementations.Library if (altVideo is not null) { altVideo.OwnerId = video.Id; + altVideo.SetPrimaryVersionId(video.Id); allItems.Add(altVideo); } } @@ -2383,6 +2383,7 @@ namespace Emby.Server.Implementations.Library if (altVideo is not null) { altVideo.OwnerId = video.Id; + altVideo.SetPrimaryVersionId(video.Id); allItems.Add(altVideo); } } diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 1c8b695458..155871770a 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -147,9 +147,9 @@ public class VideosController : BaseJellyfinApiController return NotFound(); } - if (item.LinkedAlternateVersions.Length == 0) + if (item.LinkedAlternateVersions.Length == 0 && item.PrimaryVersionId.HasValue) { - item = _libraryManager.GetItemById