diff --git a/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json b/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json index dc644387..19286296 100644 --- a/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json +++ b/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json @@ -3,11 +3,8 @@ "operationId": "02bc6448-a69d-4ff4-a0ec-0db07ec3a09a", "description": "Upgrade solution or project to new version of .NET", "startTime": "2026-03-05T22:18:32.3921759Z", - "lastUpdateTime": "2026-03-06T14:43:11.1102232Z", + "lastUpdateTime": "2026-03-07T16:26:16.8032461Z", "stage": "Execution", - "properties": { - "SelectedScenarioStrategy": "BottomUp", - "UpgradeTargetFramework": "net11.0" - }, + "properties": {}, "folderPath": "" } \ No newline at end of file diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs index 2a8c0535..f16873f4 100644 --- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs +++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs @@ -424,17 +424,13 @@ public sealed class BaseItemRepository return result; } - // Load full entities with navigations + // Load full entities with navigations and preserve the precomputed id order. var dbQueryWithNavs = ApplyNavigations(context.BaseItems.Where(e => pagedIds.Contains(e.Id)), filter); var items = await dbQueryWithNavs .ToListAsync(cancellationToken) .ConfigureAwait(false); - result.Items = items - .Where(e => e is not null) - .Select(w => DeserializeBaseItem(w, filter.SkipDeserialization)) - .Where(dto => dto is not null) - .ToArray()!; + result.Items = MaterializeOrderedDtos(items, pagedIds, filter.SkipDeserialization); result.StartIndex = filter.StartIndex ?? 0; return result; } @@ -497,24 +493,15 @@ public sealed class BaseItemRepository .ToListAsync(cancellationToken) .ConfigureAwait(false); - var itemsById = items - .Select(w => DeserializeBaseItem(w, filter.SkipDeserialization)) - .Where(dto => dto is not null) - .ToDictionary(i => i!.Id); - - return pagedIds.Where(itemsById.ContainsKey).Select(id => itemsById[id]).ToArray()!; + return MaterializeOrderedDtos(items, pagedIds, filter.SkipDeserialization); } - // Load full entities with navigations + // Load full entities with navigations and preserve the precomputed id order. var results = await ApplyNavigations(context.BaseItems.Where(e => pagedIds.Contains(e.Id)), filter) .ToListAsync(cancellationToken) .ConfigureAwait(false); - return results - .Where(e => e is not null) - .Select(w => DeserializeBaseItem(w, filter.SkipDeserialization)) - .Where(dto => dto is not null) - .ToArray()!; + return MaterializeOrderedDtos(results, pagedIds, filter.SkipDeserialization); } /// @@ -601,16 +588,12 @@ public sealed class BaseItemRepository return Array.Empty(); } - // Load full entities with navigations + // Load full entities with navigations and preserve the precomputed id order. var results = await ApplyNavigations(context.BaseItems.Where(e => pagedIds.Contains(e.Id)), filter) .ToListAsync(cancellationToken) .ConfigureAwait(false); - return results - .Where(e => e is not null) - .Select(w => DeserializeBaseItem(w, filter.SkipDeserialization)) - .Where(dto => dto is not null) - .ToArray()!; + return MaterializeOrderedDtos(results, pagedIds, filter.SkipDeserialization); } else { @@ -655,16 +638,12 @@ public sealed class BaseItemRepository return Array.Empty(); } - // Load full entities with navigations + // Load full entities with navigations and preserve the precomputed id order. var results = await ApplyNavigations(context.BaseItems.Where(e => pagedIds.Contains(e.Id)), filter) .ToListAsync(cancellationToken) .ConfigureAwait(false); - return results - .Where(e => e is not null) - .Select(w => DeserializeBaseItem(w, filter.SkipDeserialization)) - .Where(dto => dto is not null) - .ToArray()!; + return MaterializeOrderedDtos(results, pagedIds, filter.SkipDeserialization); } } } @@ -840,6 +819,21 @@ public sealed class BaseItemRepository return paged.ToList(); } + private IReadOnlyList MaterializeOrderedDtos(IReadOnlyList entities, IReadOnlyList orderedIds, bool skipDeserialization) + { + if (orderedIds.Count == 0 || entities.Count == 0) + { + return Array.Empty(); + } + + var itemsById = entities + .Select(w => DeserializeBaseItem(w, skipDeserialization)) + .Where(dto => dto is not null) + .ToDictionary(i => i!.Id); + + return orderedIds.Where(itemsById.ContainsKey).Select(id => itemsById[id]).ToArray()!; + } + private IQueryable ApplyQueryPaging(IQueryable dbQuery, InternalItemsQuery filter) { if (filter.StartIndex.HasValue && filter.StartIndex.Value > 0) diff --git a/scripts/rebuild-solution.ps1 b/rebuild-solution.ps1 similarity index 100% rename from scripts/rebuild-solution.ps1 rename to rebuild-solution.ps1