aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShadowghost <Ghost_of_Stone@web.de>2026-01-17 13:10:00 +0100
committerShadowghost <Ghost_of_Stone@web.de>2026-01-18 19:45:39 +0100
commitd3d4d37e82b9b394804f84dbdb0b873fd10f3c29 (patch)
tree9dfbd3994f6474527e61934702c70ba5a622c0df
parent1c1447362efb39b086a4fcaa1f3ece694f4d749a (diff)
Simplify UserDataManager and remove unused private methods
Removes unused private GetUserData and GetUserDataInternal methods. Moves GetUserDataBatch to be an abstract interface method rather than having a default implementation for clarity.
-rw-r--r--Emby.Server.Implementations/Library/UserDataManager.cs85
-rw-r--r--MediaBrowser.Controller/Library/IUserDataManager.cs8
2 files changed, 60 insertions, 33 deletions
diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs
index 72c8d7a9d2..9e138dbdaa 100644
--- a/Emby.Server.Implementations/Library/UserDataManager.cs
+++ b/Emby.Server.Implementations/Library/UserDataManager.cs
@@ -177,53 +177,72 @@ namespace Emby.Server.Implementations.Library
};
}
- private UserItemData? GetUserData(User user, Guid itemId, List<string> keys)
+ /// <inheritdoc />
+ public Dictionary<Guid, UserItemData> GetUserDataBatch(IReadOnlyList<BaseItem> items, User user)
{
- var cacheKey = GetCacheKey(user.InternalId, itemId);
+ var result = new Dictionary<Guid, UserItemData>(items.Count);
+ var itemsNeedingQuery = new List<(BaseItem Item, List<string> Keys)>();
- if (_cache.TryGet(cacheKey, out var data))
+ foreach (var item in items)
{
- return data;
- }
-
- data = GetUserDataInternal(user.Id, itemId, keys);
-
- if (data is null)
- {
- return new UserItemData()
+ var cacheKey = GetCacheKey(user.InternalId, item.Id);
+ if (_cache.TryGet(cacheKey, out var cachedData))
{
- Key = keys[0],
- };
+ result[item.Id] = cachedData;
+ }
+ else
+ {
+ var userData = item.UserData?.Where(e => e.UserId.Equals(user.Id)).Select(Map).FirstOrDefault();
+ if (userData is not null)
+ {
+ result[item.Id] = userData;
+ _cache.AddOrUpdate(cacheKey, userData);
+ }
+ else
+ {
+ var keys = item.GetUserDataKeys();
+ itemsNeedingQuery.Add((item, keys));
+ }
+ }
}
- return _cache.GetOrAdd(cacheKey, _ => data);
- }
-
- private UserItemData? GetUserDataInternal(Guid userId, Guid itemId, List<string> keys)
- {
- if (keys.Count == 0)
+ if (itemsNeedingQuery.Count == 0)
{
- return null;
+ return result;
}
- using var context = _repository.CreateDbContext();
- var userData = context.UserData.AsNoTracking().Where(e => e.ItemId == itemId && keys.Contains(e.CustomDataKey) && e.UserId.Equals(userId)).ToArray();
-
- if (userData.Length > 0)
+ // Build a single query for all missing items
+ var allItemIds = itemsNeedingQuery.Select(x => x.Item.Id).ToList();
+ var allKeys = itemsNeedingQuery.SelectMany(x => x.Keys).Distinct().ToList();
+ if (allKeys.Count > 0)
{
- var directDataReference = userData.FirstOrDefault(e => e.CustomDataKey == itemId.ToString("N"));
- if (directDataReference is not null)
+ using var context = _repository.CreateDbContext();
+ var userDataArray = context.UserData
+ .AsNoTracking()
+ .Where(e => allItemIds.Contains(e.ItemId) && allKeys.Contains(e.CustomDataKey) && e.UserId.Equals(user.Id))
+ .ToArray();
+
+ var userDataByItem = userDataArray.GroupBy(e => e.ItemId).ToDictionary(g => g.Key, g => g.ToArray());
+ foreach (var (item, keys) in itemsNeedingQuery)
{
- return Map(directDataReference);
- }
+ UserItemData userData;
+ if (userDataByItem.TryGetValue(item.Id, out var itemUserData) && itemUserData.Length > 0)
+ {
+ var directDataReference = itemUserData.FirstOrDefault(e => e.CustomDataKey == item.Id.ToString("N"));
+ userData = directDataReference is not null ? Map(directDataReference) : Map(itemUserData.First());
+ }
+ else
+ {
+ userData = new UserItemData { Key = keys.Count > 0 ? keys[0] : string.Empty };
+ }
- return Map(userData.First());
+ result[item.Id] = userData;
+ var cacheKey = GetCacheKey(user.InternalId, item.Id);
+ _cache.AddOrUpdate(cacheKey, userData);
+ }
}
- return new UserItemData
- {
- Key = keys.Last()!
- };
+ return result;
}
/// <summary>
diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs
index eb46611dd9..798812bf1f 100644
--- a/MediaBrowser.Controller/Library/IUserDataManager.cs
+++ b/MediaBrowser.Controller/Library/IUserDataManager.cs
@@ -55,6 +55,14 @@ namespace MediaBrowser.Controller.Library
UserItemDataDto? GetUserDataDto(BaseItem item, User user);
/// <summary>
+ /// Gets user data for multiple items in a single batch operation.
+ /// </summary>
+ /// <param name="items">The items to get user data for.</param>
+ /// <param name="user">The user.</param>
+ /// <returns>A dictionary mapping item IDs to their user data.</returns>
+ Dictionary<Guid, UserItemData> GetUserDataBatch(IReadOnlyList<BaseItem> items, User user);
+
+ /// <summary>
/// Gets the user data dto.
/// </summary>
/// <param name="item">Item to use.</param>