فهرست منبع

support multiple user data keys

Luke Pulverenti 9 سال پیش
والد
کامیت
6330b13262
26فایلهای تغییر یافته به همراه214 افزوده شده و 263 حذف شده
  1. 16 18
      MediaBrowser.Controller/Entities/Audio/Audio.cs
  2. 15 17
      MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
  3. 10 9
      MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
  4. 5 6
      MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
  5. 8 4
      MediaBrowser.Controller/Entities/BaseItem.cs
  6. 4 3
      MediaBrowser.Controller/Entities/Game.cs
  7. 5 6
      MediaBrowser.Controller/Entities/GameGenre.cs
  8. 6 7
      MediaBrowser.Controller/Entities/GameSystem.cs
  9. 5 6
      MediaBrowser.Controller/Entities/Genre.cs
  10. 4 1
      MediaBrowser.Controller/Entities/IHasUserData.cs
  11. 0 28
      MediaBrowser.Controller/Entities/Movies/Movie.cs
  12. 0 9
      MediaBrowser.Controller/Entities/MusicVideo.cs
  13. 5 6
      MediaBrowser.Controller/Entities/Person.cs
  14. 5 6
      MediaBrowser.Controller/Entities/Studio.cs
  15. 14 8
      MediaBrowser.Controller/Entities/TV/Episode.cs
  16. 7 9
      MediaBrowser.Controller/Entities/TV/Season.cs
  17. 14 12
      MediaBrowser.Controller/Entities/TV/Series.cs
  18. 0 20
      MediaBrowser.Controller/Entities/Trailer.cs
  19. 48 10
      MediaBrowser.Controller/Entities/Video.cs
  20. 5 6
      MediaBrowser.Controller/Entities/Year.cs
  21. 2 5
      MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs
  22. 0 11
      MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
  23. 5 6
      MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
  24. 16 12
      MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
  25. 0 26
      MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
  26. 15 12
      MediaBrowser.Server.Implementations/Library/UserDataManager.cs

+ 16 - 18
MediaBrowser.Controller/Entities/Audio/Audio.cs

@@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Entities.Audio
         IArchivable
     {
         public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
-        
+
         public long? Size { get; set; }
         public string Container { get; set; }
         public int? TotalBitrate { get; set; }
@@ -150,12 +150,10 @@ namespace MediaBrowser.Controller.Entities.Audio
                     + (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
         }
 
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
+            var list = base.GetUserDataKeys();
+
             if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
             {
                 var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty;
@@ -165,7 +163,7 @@ namespace MediaBrowser.Controller.Entities.Audio
                 {
                     songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey;
                 }
-                songKey+= Name;
+                songKey += Name;
 
                 if (!string.IsNullOrWhiteSpace(Album))
                 {
@@ -178,25 +176,25 @@ namespace MediaBrowser.Controller.Entities.Audio
                     songKey = albumArtist + "-" + songKey;
                 }
 
-                return songKey;
+                list.Insert(0, songKey);
             }
-
-            var parent = AlbumEntity;
-
-            if (parent != null)
+            else
             {
-                var parentKey = parent.GetUserDataKey();
+                var parent = AlbumEntity;
 
-                if (IndexNumber.HasValue)
+                if (parent != null && IndexNumber.HasValue)
                 {
-                    var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
-                                  + IndexNumber.Value.ToString("0000 - ");
+                    list.InsertRange(0, parent.GetUserDataKeys().Select(i =>
+                    {
+                        var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
+                                      + IndexNumber.Value.ToString("0000 - ");
 
-                    return parentKey + songKey;
+                        return i + songKey;
+                    }));
                 }
             }
 
-            return base.CreateUserDataKey();
+            return list;
         }
 
         public override UnratedItem GetBlockUnratedType()

+ 15 - 17
MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs

@@ -96,36 +96,34 @@ namespace MediaBrowser.Controller.Entities.Audio
 
         public List<string> Artists { get; set; }
 
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            var id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+            var list = base.GetUserDataKeys();
 
-            if (!string.IsNullOrWhiteSpace(id))
+            if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
             {
-                return "MusicAlbum-MusicBrainzReleaseGroup-" + id;
+                var albumArtist = AlbumArtist;
+                if (!string.IsNullOrWhiteSpace(albumArtist))
+                {
+                    list.Insert(0, albumArtist + "-" + Name);
+                }
             }
 
-            id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum);
+            var id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum);
 
             if (!string.IsNullOrWhiteSpace(id))
             {
-                return "MusicAlbum-Musicbrainz-" + id;
+                list.Insert(0, "MusicAlbum-Musicbrainz-" + id);
             }
 
-            if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
+            id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+
+            if (!string.IsNullOrWhiteSpace(id))
             {
-                var albumArtist = AlbumArtist;
-                if (!string.IsNullOrWhiteSpace(albumArtist))
-                {
-                    return albumArtist + "-" + Name;
-                }
+                list.Insert(0, "MusicAlbum-MusicBrainzReleaseGroup-" + id);
             }
 
-            return base.CreateUserDataKey();
+            return list;
         }
 
         protected override bool GetBlockUnratedValue(UserPolicy config)

+ 10 - 9
MediaBrowser.Controller/Entities/Audio/MusicArtist.cs

@@ -80,13 +80,12 @@ namespace MediaBrowser.Controller.Entities.Audio
             ProductionLocations = new List<string>();
         }
 
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            return GetUserDataKey(this);
+            var list = base.GetUserDataKeys();
+
+            list.InsertRange(0, GetUserDataKeys(this));
+            return list;
         }
 
         /// <summary>
@@ -121,16 +120,18 @@ namespace MediaBrowser.Controller.Entities.Audio
         /// </summary>
         /// <param name="item">The item.</param>
         /// <returns>System.String.</returns>
-        private static string GetUserDataKey(MusicArtist item)
+        private static List<string> GetUserDataKeys(MusicArtist item)
         {
+            var list = new List<string>();
             var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
 
             if (!string.IsNullOrEmpty(id))
             {
-                return "Artist-Musicbrainz-" + id;
+                list.Add("Artist-Musicbrainz-" + id);
             }
 
-            return "Artist-" + item.Name;
+            list.Add("Artist-" + item.Name);
+            return list;
         }
 
         protected override bool GetBlockUnratedValue(UserPolicy config)

+ 5 - 6
MediaBrowser.Controller/Entities/Audio/MusicGenre.cs

@@ -10,13 +10,12 @@ namespace MediaBrowser.Controller.Entities.Audio
     /// </summary>
     public class MusicGenre : BaseItem, IItemByName
     {
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            return "MusicGenre-" + Name;
+            var list = base.GetUserDataKeys();
+
+            list.Insert(0, "MusicGenre-" + Name);
+            return list;
         }
 
         [IgnoreDataMember]

+ 8 - 4
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -1158,7 +1158,7 @@ namespace MediaBrowser.Controller.Entities
         {
             if (string.IsNullOrWhiteSpace(_userDataKey))
             {
-                var key = CreateUserDataKey();
+                var key = GetUserDataKeys().First();
                 _userDataKey = key;
                 return key;
             }
@@ -1166,16 +1166,20 @@ namespace MediaBrowser.Controller.Entities
             return _userDataKey;
         }
 
-        protected virtual string CreateUserDataKey()
+        public virtual List<string> GetUserDataKeys()
         {
+            var list = new List<string>();
+
             if (SourceType == SourceType.Channel)
             {
                 if (!string.IsNullOrWhiteSpace(ExternalId))
                 {
-                    return ExternalId;
+                    list.Add(ExternalId);
                 }
             }
-            return Id.ToString();
+
+            list.Add(Id.ToString());
+            return list;
         }
 
         internal virtual bool IsValidFromResolver(BaseItem newItem)

+ 4 - 3
MediaBrowser.Controller/Entities/Game.cs

@@ -76,15 +76,16 @@ namespace MediaBrowser.Controller.Entities
         /// </summary>
         public List<string> MultiPartGameFiles { get; set; }
 
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
+            var list = base.GetUserDataKeys();
             var id = this.GetProviderId(MetadataProviders.Gamesdb);
 
             if (!string.IsNullOrEmpty(id))
             {
-                return "Game-Gamesdb-" + id;
+                list.Insert(0, "Game-Gamesdb-" + id);
             }
-            return base.CreateUserDataKey();
+            return list;
         }
 
         public override IEnumerable<string> GetDeletePaths()

+ 5 - 6
MediaBrowser.Controller/Entities/GameGenre.cs

@@ -7,13 +7,12 @@ namespace MediaBrowser.Controller.Entities
 {
     public class GameGenre : BaseItem, IItemByName
     {
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            return "GameGenre-" + Name;
+            var list = base.GetUserDataKeys();
+
+            list.Insert(0, "GameGenre-" + Name);
+            return list;
         }
 
         /// <summary>

+ 6 - 7
MediaBrowser.Controller/Entities/GameSystem.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Configuration;
 using System;
+using System.Collections.Generic;
 using MediaBrowser.Model.Users;
 
 namespace MediaBrowser.Controller.Entities
@@ -31,17 +32,15 @@ namespace MediaBrowser.Controller.Entities
         /// <value>The game system.</value>
         public string GameSystemName { get; set; }
 
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
+            var list = base.GetUserDataKeys();
+
             if (!string.IsNullOrEmpty(GameSystemName))
             {
-                return "GameSystem-" + GameSystemName;
+                list.Insert(0, "GameSystem-" + GameSystemName);
             }
-            return base.CreateUserDataKey();
+            return list;
         }
 
         protected override bool GetBlockUnratedValue(UserPolicy config)

+ 5 - 6
MediaBrowser.Controller/Entities/Genre.cs

@@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.Entities
     /// </summary>
     public class Genre : BaseItem, IItemByName
     {
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            return "Genre-" + Name;
+            var list = base.GetUserDataKeys();
+
+            list.Insert(0, "Genre-" + Name);
+            return list;
         }
 
         /// <summary>

+ 4 - 1
MediaBrowser.Controller/Entities/IHasUserData.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Dto;
+using System.Collections.Generic;
+using MediaBrowser.Model.Dto;
 
 namespace MediaBrowser.Controller.Entities
 {
@@ -13,6 +14,8 @@ namespace MediaBrowser.Controller.Entities
         /// <returns>System.String.</returns>
         string GetUserDataKey();
 
+        List<string> GetUserDataKeys();
+
         /// <summary>
         /// Fills the user data dto values.
         /// </summary>

+ 0 - 28
MediaBrowser.Controller/Entities/Movies/Movie.cs

@@ -75,34 +75,6 @@ namespace MediaBrowser.Controller.Entities.Movies
             get { return TmdbCollectionName; }
             set { TmdbCollectionName = value; }
         }
-        
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
-        {
-            var key = GetMovieUserDataKey(this);
-
-            if (string.IsNullOrWhiteSpace(key))
-            {
-                key = base.CreateUserDataKey();
-            }
-
-            return key;
-        }
-
-        public static string GetMovieUserDataKey(BaseItem movie)
-        {
-            var key = movie.GetProviderId(MetadataProviders.Tmdb);
-
-            if (string.IsNullOrWhiteSpace(key))
-            {
-                key = movie.GetProviderId(MetadataProviders.Imdb);
-            }
-
-            return key;
-        }
 
         protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
         {

+ 0 - 9
MediaBrowser.Controller/Entities/MusicVideo.cs

@@ -44,15 +44,6 @@ namespace MediaBrowser.Controller.Entities
             }
         }
 
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
-        {
-            return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey();
-        }
-
         public override UnratedItem GetBlockUnratedType()
         {
             return UnratedItem.Music;

+ 5 - 6
MediaBrowser.Controller/Entities/Person.cs

@@ -18,13 +18,12 @@ namespace MediaBrowser.Controller.Entities
         /// <value>The place of birth.</value>
         public string PlaceOfBirth { get; set; }
 
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            return "Person-" + Name;
+            var list = base.GetUserDataKeys();
+
+            list.Insert(0, "Person-" + Name);
+            return list;
         }
 
         public PersonLookupInfo GetLookupInfo()

+ 5 - 6
MediaBrowser.Controller/Entities/Studio.cs

@@ -10,13 +10,12 @@ namespace MediaBrowser.Controller.Entities
     /// </summary>
     public class Studio : BaseItem, IItemByName, IHasTags
     {
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            return "Studio-" + Name;
+            var list = base.GetUserDataKeys();
+
+            list.Insert(0, "Studio-" + Name);
+            return list;
         }
 
         /// <summary>

+ 14 - 8
MediaBrowser.Controller/Entities/TV/Episode.cs

@@ -98,20 +98,26 @@ namespace MediaBrowser.Controller.Entities.TV
             }
         }
 
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        [IgnoreDataMember]
+        protected override bool EnableDefaultVideoUserDataKeys
         {
-            var series = Series;
+            get
+            {
+                return false;
+            }
+        }
+
+        public override List<string> GetUserDataKeys()
+        {
+            var list = base.GetUserDataKeys();
 
+            var series = Series;
             if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
             {
-                return series.GetUserDataKey() + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000");
+                list.InsertRange(0, series.GetUserDataKeys().Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
             }
 
-            return base.CreateUserDataKey();
+            return list;
         }
 
         /// <summary>

+ 7 - 9
MediaBrowser.Controller/Entities/TV/Season.cs

@@ -53,19 +53,17 @@ namespace MediaBrowser.Controller.Entities.TV
             };
         }
 
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            if (Series != null)
+            var list = base.GetUserDataKeys();
+
+            var series = Series;
+            if (series != null)
             {
-                var seasonNo = IndexNumber ?? 0;
-                return Series.GetUserDataKey() + seasonNo.ToString("000");
+                list.InsertRange(0, series.GetUserDataKeys().Select(i => i + (IndexNumber ?? 0).ToString("000")));
             }
 
-            return base.CreateUserDataKey();
+            return list;
         }
 
         /// <summary>

+ 14 - 12
MediaBrowser.Controller/Entities/TV/Series.cs

@@ -95,21 +95,23 @@ namespace MediaBrowser.Controller.Entities.TV
         /// Gets the user data key.
         /// </summary>
         /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            var key = this.GetProviderId(MetadataProviders.Tvdb);
+            var list = base.GetUserDataKeys();
 
-            if (string.IsNullOrWhiteSpace(key))
+            var key = this.GetProviderId(MetadataProviders.Imdb);
+            if (!string.IsNullOrWhiteSpace(key))
             {
-                key = this.GetProviderId(MetadataProviders.Imdb);
+                list.Insert(0, key);
             }
 
-            if (string.IsNullOrWhiteSpace(key))
+            key = this.GetProviderId(MetadataProviders.Tvdb);
+            if (!string.IsNullOrWhiteSpace(key))
             {
-                key = base.CreateUserDataKey();
+                list.Insert(0, key);
             }
 
-            return key;
+            return list;
         }
 
         /// <summary>
@@ -126,8 +128,8 @@ namespace MediaBrowser.Controller.Entities.TV
         // Studio, Genre and Rating will all be the same so makes no sense to index by these
         protected override IEnumerable<string> GetIndexByOptions()
         {
-            return new List<string> {            
-                {"None"}, 
+            return new List<string> {
+                {"None"},
                 {"Performer"},
                 {"Director"},
                 {"Year"},
@@ -280,9 +282,9 @@ namespace MediaBrowser.Controller.Entities.TV
                 if (episode != null
                     && refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh
                     && !refreshOptions.ReplaceAllMetadata
-                    && episode.IsMissingEpisode 
-                    && episode.LocationType == Model.Entities.LocationType.Virtual 
-                    && episode.PremiereDate.HasValue 
+                    && episode.IsMissingEpisode
+                    && episode.LocationType == Model.Entities.LocationType.Virtual
+                    && episode.PremiereDate.HasValue
                     && (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30)
                 {
                     skipItem = true;

+ 0 - 20
MediaBrowser.Controller/Entities/Trailer.cs

@@ -56,26 +56,6 @@ namespace MediaBrowser.Controller.Entities
         /// <value>The revenue.</value>
         public double? Revenue { get; set; }
 
-        protected override string CreateUserDataKey()
-        {
-            var key = Movie.GetMovieUserDataKey(this);
-
-            if (!string.IsNullOrWhiteSpace(key))
-            {
-                key = key + "-trailer";
-
-                // Make sure different trailers have their own data.
-                if (RunTimeTicks.HasValue)
-                {
-                    key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
-                }
-
-                return key;
-            }
-
-            return base.CreateUserDataKey();
-        }
-
         public override UnratedItem GetBlockUnratedType()
         {
             return UnratedItem.Trailer;

+ 48 - 10
MediaBrowser.Controller/Entities/Video.cs

@@ -131,27 +131,65 @@ namespace MediaBrowser.Controller.Entities
             return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
         }
 
-        protected override string CreateUserDataKey()
+        [IgnoreDataMember]
+        protected virtual bool EnableDefaultVideoUserDataKeys
         {
-            if (ExtraType.HasValue)
+            get
             {
-                var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb);
+                return true;
+            }
+        }
+
+        public override List<string> GetUserDataKeys()
+        {
+            var list = base.GetUserDataKeys();
 
-                if (!string.IsNullOrWhiteSpace(key))
+            if (EnableDefaultVideoUserDataKeys)
+            {
+                if (ExtraType.HasValue)
                 {
-                    key = key + "-" + ExtraType.ToString().ToLower();
+                    var key = this.GetProviderId(MetadataProviders.Tmdb);
+                    if (!string.IsNullOrWhiteSpace(key))
+                    {
+                        list.Insert(0, GetUserDataKey(key));
+                    }
 
-                    // Make sure different trailers have their own data.
-                    if (RunTimeTicks.HasValue)
+                    key = this.GetProviderId(MetadataProviders.Imdb);
+                    if (!string.IsNullOrWhiteSpace(key))
                     {
-                        key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
+                        list.Insert(0, GetUserDataKey(key));
+                    }
+                }
+                else
+                {
+                    var key = this.GetProviderId(MetadataProviders.Imdb);
+                    if (!string.IsNullOrWhiteSpace(key))
+                    {
+                        list.Insert(0, key);
                     }
 
-                    return key;
+                    key = this.GetProviderId(MetadataProviders.Tmdb);
+                    if (!string.IsNullOrWhiteSpace(key))
+                    {
+                        list.Insert(0, key);
+                    }
                 }
             }
 
-            return base.CreateUserDataKey();
+            return list;
+        }
+
+        private string GetUserDataKey(string providerId)
+        {
+            var key = providerId + "-" + ExtraType.ToString().ToLower();
+
+            // Make sure different trailers have their own data.
+            if (RunTimeTicks.HasValue)
+            {
+                key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
+            }
+
+            return key;
         }
 
         /// <summary>

+ 5 - 6
MediaBrowser.Controller/Entities/Year.cs

@@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.Entities
     /// </summary>
     public class Year : BaseItem, IItemByName
     {
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            return "Year-" + Name;
+            var list = base.GetUserDataKeys();
+
+            list.Insert(0, "Year-" + Name);
+            return list;
         }
 
         /// <summary>

+ 2 - 5
MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs

@@ -1,6 +1,7 @@
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Entities;
 using System;
+using System.Collections.Generic;
 
 namespace MediaBrowser.Controller.Library
 {
@@ -15,11 +16,7 @@ namespace MediaBrowser.Controller.Library
         /// <value>The user id.</value>
         public Guid UserId { get; set; }
 
-        /// <summary>
-        /// Gets or sets the key.
-        /// </summary>
-        /// <value>The key.</value>
-        public string Key { get; set; }
+        public List<string> Keys { get; set; }
 
         /// <summary>
         /// Gets or sets the save reason.

+ 0 - 11
MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs

@@ -45,17 +45,6 @@ namespace MediaBrowser.Controller.LiveTv
             set { }
         }
 
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
-        {
-            var name = GetClientTypeName();
-
-            return name + "-" + Name + (EpisodeTitle ?? string.Empty);
-        }
-
         /// <summary>
         /// Gets a value indicating whether this instance is owned item.
         /// </summary>

+ 5 - 6
MediaBrowser.Controller/LiveTv/LiveTvChannel.cs

@@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.LiveTv
 {
     public class LiveTvChannel : BaseItem, IHasMediaSources
     {
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            return GetClientTypeName() + "-" + Name;
+            var list = base.GetUserDataKeys();
+
+            list.Insert(0, GetClientTypeName() + "-" + Name);
+            return list;
         }
 
         public override UnratedItem GetBlockUnratedType()

+ 16 - 12
MediaBrowser.Controller/LiveTv/LiveTvProgram.cs

@@ -4,36 +4,40 @@ using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.LiveTv;
 using System;
+using System.Collections.Generic;
 using System.Runtime.Serialization;
+using MediaBrowser.Model.Entities;
 
 namespace MediaBrowser.Controller.LiveTv
 {
     public class LiveTvProgram : BaseItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
     {
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
+        public override List<string> GetUserDataKeys()
         {
-            if (IsMovie)
+            var list = base.GetUserDataKeys();
+
+            if (!IsSeries)
             {
-                var key = Movie.GetMovieUserDataKey(this);
+                var key = this.GetProviderId(MetadataProviders.Imdb);
+                if (!string.IsNullOrWhiteSpace(key))
+                {
+                    list.Insert(0, key);
+                }
 
+                key = this.GetProviderId(MetadataProviders.Tmdb);
                 if (!string.IsNullOrWhiteSpace(key))
                 {
-                    return key;
+                    list.Insert(0, key);
                 }
             }
-
-            if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle))
+            else if (!string.IsNullOrWhiteSpace(EpisodeTitle))
             {
                 var name = GetClientTypeName();
 
-                return name + "-" + Name + (EpisodeTitle ?? string.Empty);
+                list.Insert(0, name + "-" + Name + (EpisodeTitle ?? string.Empty));
             }
 
-            return base.CreateUserDataKey();
+            return list;
         }
 
         [IgnoreDataMember]

+ 0 - 26
MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs

@@ -45,32 +45,6 @@ namespace MediaBrowser.Controller.LiveTv
             set { }
         }
 
-        /// <summary>
-        /// Gets the user data key.
-        /// </summary>
-        /// <returns>System.String.</returns>
-        protected override string CreateUserDataKey()
-        {
-            if (IsMovie)
-            {
-                var key = Movie.GetMovieUserDataKey(this);
-
-                if (!string.IsNullOrWhiteSpace(key))
-                {
-                    return key;
-                }
-            }
-
-            if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle))
-            {
-                var name = GetClientTypeName();
-
-                return name + "-" + Name + (EpisodeTitle ?? string.Empty);
-            }
-
-            return base.CreateUserDataKey();
-        }
-
         [IgnoreDataMember]
         public override string MediaType
         {

+ 15 - 12
MediaBrowser.Server.Implementations/Library/UserDataManager.cs

@@ -56,27 +56,30 @@ namespace MediaBrowser.Server.Implementations.Library
 
             cancellationToken.ThrowIfCancellationRequested();
 
-            var key = item.GetUserDataKey();
+            var keys = item.GetUserDataKeys();
 
-            try
+            foreach (var key in keys)
             {
-                await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false);
+                try
+                {
+                    await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false);
 
-                var newValue = userData;
+                    var newValue = userData;
 
-                // Once it succeeds, put it into the dictionary to make it available to everyone else
-                _userData.AddOrUpdate(GetCacheKey(userId, key), newValue, delegate { return newValue; });
-            }
-            catch (Exception ex)
-            {
-                _logger.ErrorException("Error saving user data", ex);
+                    // Once it succeeds, put it into the dictionary to make it available to everyone else
+                    _userData.AddOrUpdate(GetCacheKey(userId, key), newValue, delegate { return newValue; });
+                }
+                catch (Exception ex)
+                {
+                    _logger.ErrorException("Error saving user data", ex);
 
-                throw;
+                    throw;
+                }
             }
 
             EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs
             {
-                Key = key,
+                Keys = keys,
                 UserData = userData,
                 SaveReason = reason,
                 UserId = userId,