浏览代码

Merge pull request #5395 from barronpm/ef-cleanup

Bond-009 4 年之前
父节点
当前提交
f2125da9f9
共有 60 个文件被更改,包括 136 次插入746 次删除
  1. 6 1
      Emby.Drawing/ImageProcessor.cs
  2. 1 0
      Emby.Server.Implementations/Emby.Server.Implementations.csproj
  3. 11 1
      Jellyfin.Api/Controllers/ImageController.cs
  4. 4 1
      Jellyfin.Api/Controllers/StartupController.cs
  5. 0 29
      Jellyfin.Data/Entities/AccessSchedule.cs
  6. 5 16
      Jellyfin.Data/Entities/ActivityLog.cs
  7. 5 15
      Jellyfin.Data/Entities/CustomItemDisplayPreferences.cs
  8. 2 12
      Jellyfin.Data/Entities/DisplayPreferences.cs
  9. 0 11
      Jellyfin.Data/Entities/Group.cs
  10. 0 1
      Jellyfin.Data/Entities/HomeSection.cs
  11. 0 11
      Jellyfin.Data/Entities/ImageInfo.cs
  12. 0 9
      Jellyfin.Data/Entities/ItemDisplayPreferences.cs
  13. 1 15
      Jellyfin.Data/Entities/Libraries/Artwork.cs
  14. 2 1
      Jellyfin.Data/Entities/Libraries/Book.cs
  15. 1 22
      Jellyfin.Data/Entities/Libraries/BookMetadata.cs
  16. 2 21
      Jellyfin.Data/Entities/Libraries/Chapter.cs
  17. 1 1
      Jellyfin.Data/Entities/Libraries/Collection.cs
  18. 5 35
      Jellyfin.Data/Entities/Libraries/CollectionItem.cs
  19. 2 15
      Jellyfin.Data/Entities/Libraries/Company.cs
  20. 5 20
      Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs
  21. 2 1
      Jellyfin.Data/Entities/Libraries/CustomItem.cs
  22. 1 20
      Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs
  23. 2 20
      Jellyfin.Data/Entities/Libraries/Episode.cs
  24. 4 22
      Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs
  25. 1 26
      Jellyfin.Data/Entities/Libraries/Genre.cs
  26. 2 14
      Jellyfin.Data/Entities/Libraries/ItemMetadata.cs
  27. 3 19
      Jellyfin.Data/Entities/Libraries/Library.cs
  28. 0 8
      Jellyfin.Data/Entities/Libraries/LibraryItem.cs
  29. 1 20
      Jellyfin.Data/Entities/Libraries/MediaFile.cs
  30. 1 20
      Jellyfin.Data/Entities/Libraries/MediaFileStream.cs
  31. 0 11
      Jellyfin.Data/Entities/Libraries/MetadataProvider.cs
  32. 3 20
      Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs
  33. 2 1
      Jellyfin.Data/Entities/Libraries/Movie.cs
  34. 5 20
      Jellyfin.Data/Entities/Libraries/MovieMetadata.cs
  35. 2 1
      Jellyfin.Data/Entities/Libraries/MusicAlbum.cs
  36. 4 17
      Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs
  37. 1 12
      Jellyfin.Data/Entities/Libraries/Person.cs
  38. 5 23
      Jellyfin.Data/Entities/Libraries/PersonRole.cs
  39. 2 1
      Jellyfin.Data/Entities/Libraries/Photo.cs
  40. 1 20
      Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs
  41. 2 21
      Jellyfin.Data/Entities/Libraries/Rating.cs
  42. 3 22
      Jellyfin.Data/Entities/Libraries/RatingSource.cs
  43. 1 15
      Jellyfin.Data/Entities/Libraries/Release.cs
  44. 2 20
      Jellyfin.Data/Entities/Libraries/Season.cs
  45. 2 20
      Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs
  46. 2 1
      Jellyfin.Data/Entities/Libraries/Series.cs
  47. 5 25
      Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs
  48. 2 20
      Jellyfin.Data/Entities/Libraries/Track.cs
  49. 1 20
      Jellyfin.Data/Entities/Libraries/TrackMetadata.cs
  50. 0 8
      Jellyfin.Data/Entities/Permission.cs
  51. 0 9
      Jellyfin.Data/Entities/Preference.cs
  52. 7 18
      Jellyfin.Data/Entities/User.cs
  53. 1 1
      Jellyfin.Data/Interfaces/IHasPermissions.cs
  54. 2 2
      Jellyfin.Data/Jellyfin.Data.csproj
  55. 2 2
      Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs
  56. 2 0
      Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
  57. 3 3
      Jellyfin.Server.Implementations/Users/UserManager.cs
  58. 1 3
      Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs
  59. 1 1
      MediaBrowser.Controller/Drawing/IImageProcessor.cs
  60. 2 2
      tests/Jellyfin.Api.Tests/TestHelpers.cs

+ 6 - 1
Emby.Drawing/ImageProcessor.cs

@@ -352,8 +352,13 @@ namespace Emby.Drawing
         }
 
         /// <inheritdoc />
-        public string GetImageCacheTag(User user)
+        public string? GetImageCacheTag(User user)
         {
+            if (user.ProfileImage == null)
+            {
+                return null;
+            }
+
             return (user.ProfileImage.Path + user.ProfileImage.LastModified.Ticks).GetMD5()
                 .ToString("N", CultureInfo.InvariantCulture);
         }

+ 1 - 0
Emby.Server.Implementations/Emby.Server.Implementations.csproj

@@ -27,6 +27,7 @@
     <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />
     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
     <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.3" />
     <PackageReference Include="Mono.Nat" Version="3.0.1" />
     <PackageReference Include="prometheus-net.DotNetRuntime" Version="3.4.1" />
     <PackageReference Include="sharpcompress" Version="0.28.1" />

+ 11 - 1
Jellyfin.Api/Controllers/ImageController.cs

@@ -196,6 +196,11 @@ namespace Jellyfin.Api.Controllers
             }
 
             var user = _userManager.GetUserById(userId);
+            if (user?.ProfileImage == null)
+            {
+                return NoContent();
+            }
+
             try
             {
                 System.IO.File.Delete(user.ProfileImage.Path);
@@ -235,6 +240,11 @@ namespace Jellyfin.Api.Controllers
             }
 
             var user = _userManager.GetUserById(userId);
+            if (user?.ProfileImage == null)
+            {
+                return NoContent();
+            }
+
             try
             {
                 System.IO.File.Delete(user.ProfileImage.Path);
@@ -1469,7 +1479,7 @@ namespace Jellyfin.Api.Controllers
             [FromQuery] int? imageIndex)
         {
             var user = _userManager.GetUserById(userId);
-            if (user == null)
+            if (user?.ProfileImage == null)
             {
                 return NotFound();
             }

+ 4 - 1
Jellyfin.Api/Controllers/StartupController.cs

@@ -132,7 +132,10 @@ namespace Jellyfin.Api.Controllers
         {
             var user = _userManager.Users.First();
 
-            user.Username = startupUserDto.Name;
+            if (startupUserDto.Name != null)
+            {
+                user.Username = startupUserDto.Name;
+            }
 
             await _userManager.UpdateUserAsync(user).ConfigureAwait(false);
 

+ 0 - 29
Jellyfin.Data/Entities/AccessSchedule.cs

@@ -1,7 +1,5 @@
 using System;
-using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
-using System.Text.Json.Serialization;
 using System.Xml.Serialization;
 using Jellyfin.Data.Enums;
 
@@ -27,14 +25,6 @@ namespace Jellyfin.Data.Entities
             EndHour = endHour;
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="AccessSchedule"/> class.
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </summary>
-        protected AccessSchedule()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id of this instance.
         /// </summary>
@@ -42,8 +32,6 @@ namespace Jellyfin.Data.Entities
         /// Identity, Indexed, Required.
         /// </remarks>
         [XmlIgnore]
-        [Key]
-        [Required]
         [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
         public int Id { get; protected set; }
 
@@ -51,41 +39,24 @@ namespace Jellyfin.Data.Entities
         /// Gets or sets the id of the associated user.
         /// </summary>
         [XmlIgnore]
-        [Required]
         public Guid UserId { get; protected set; }
 
         /// <summary>
         /// Gets or sets the day of week.
         /// </summary>
         /// <value>The day of week.</value>
-        [Required]
         public DynamicDayOfWeek DayOfWeek { get; set; }
 
         /// <summary>
         /// Gets or sets the start hour.
         /// </summary>
         /// <value>The start hour.</value>
-        [Required]
         public double StartHour { get; set; }
 
         /// <summary>
         /// Gets or sets the end hour.
         /// </summary>
         /// <value>The end hour.</value>
-        [Required]
         public double EndHour { get; set; }
-
-        /// <summary>
-        /// Static create function (for use in LINQ queries, etc.)
-        /// </summary>
-        /// <param name="dayOfWeek">The day of the week.</param>
-        /// <param name="startHour">The start hour.</param>
-        /// <param name="endHour">The end hour.</param>
-        /// <param name="userId">The associated user's id.</param>
-        /// <returns>The newly created instance.</returns>
-        public static AccessSchedule Create(DynamicDayOfWeek dayOfWeek, double startHour, double endHour, Guid userId)
-        {
-            return new AccessSchedule(dayOfWeek, startHour, endHour, userId);
-        }
     }
 }

+ 5 - 16
Jellyfin.Data/Entities/ActivityLog.cs

@@ -18,8 +18,7 @@ namespace Jellyfin.Data.Entities
         /// <param name="name">The name.</param>
         /// <param name="type">The type.</param>
         /// <param name="userId">The user id.</param>
-        /// <param name="logLevel">The log level.</param>
-        public ActivityLog(string name, string type, Guid userId, LogLevel logLevel = LogLevel.Information)
+        public ActivityLog(string name, string type, Guid userId)
         {
             if (string.IsNullOrEmpty(name))
             {
@@ -35,15 +34,7 @@ namespace Jellyfin.Data.Entities
             Type = type;
             UserId = userId;
             DateCreated = DateTime.UtcNow;
-            LogSeverity = logLevel;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ActivityLog"/> class.
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </summary>
-        protected ActivityLog()
-        {
+            LogSeverity = LogLevel.Information;
         }
 
         /// <summary>
@@ -59,7 +50,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required, Max length = 512.
         /// </remarks>
-        [Required]
         [MaxLength(512)]
         [StringLength(512)]
         public string Name { get; set; }
@@ -72,7 +62,7 @@ namespace Jellyfin.Data.Entities
         /// </remarks>
         [MaxLength(512)]
         [StringLength(512)]
-        public string Overview { get; set; }
+        public string? Overview { get; set; }
 
         /// <summary>
         /// Gets or sets the short overview.
@@ -82,7 +72,7 @@ namespace Jellyfin.Data.Entities
         /// </remarks>
         [MaxLength(512)]
         [StringLength(512)]
-        public string ShortOverview { get; set; }
+        public string? ShortOverview { get; set; }
 
         /// <summary>
         /// Gets or sets the type.
@@ -90,7 +80,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required, Max length = 256.
         /// </remarks>
-        [Required]
         [MaxLength(256)]
         [StringLength(256)]
         public string Type { get; set; }
@@ -111,7 +100,7 @@ namespace Jellyfin.Data.Entities
         /// </remarks>
         [MaxLength(256)]
         [StringLength(256)]
-        public string ItemId { get; set; }
+        public string? ItemId { get; set; }
 
         /// <summary>
         /// Gets or sets the date created. This should be in UTC.

+ 5 - 15
Jellyfin.Data/Entities/CustomItemDisplayPreferences.cs

@@ -15,22 +15,15 @@ namespace Jellyfin.Data.Entities
         /// <param name="userId">The user id.</param>
         /// <param name="itemId">The item id.</param>
         /// <param name="client">The client.</param>
-        /// <param name="preferenceKey">The preference key.</param>
-        /// <param name="preferenceValue">The preference value.</param>
-        public CustomItemDisplayPreferences(Guid userId, Guid itemId, string client, string preferenceKey, string preferenceValue)
+        /// <param name="key">The preference key.</param>
+        /// <param name="value">The preference value.</param>
+        public CustomItemDisplayPreferences(Guid userId, Guid itemId, string client, string key, string value)
         {
             UserId = userId;
             ItemId = itemId;
             Client = client;
-            Key = preferenceKey;
-            Value = preferenceValue;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CustomItemDisplayPreferences"/> class.
-        /// </summary>
-        protected CustomItemDisplayPreferences()
-        {
+            Key = key;
+            Value = value;
         }
 
         /// <summary>
@@ -64,7 +57,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required. Max Length = 32.
         /// </remarks>
-        [Required]
         [MaxLength(32)]
         [StringLength(32)]
         public string Client { get; set; }
@@ -75,7 +67,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required.
         /// </remarks>
-        [Required]
         public string Key { get; set; }
 
         /// <summary>
@@ -84,7 +75,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required.
         /// </remarks>
-        [Required]
         public string Value { get; set; }
     }
 }

+ 2 - 12
Jellyfin.Data/Entities/DisplayPreferences.cs

@@ -30,19 +30,10 @@ namespace Jellyfin.Data.Entities
             SkipBackwardLength = 10000;
             ScrollDirection = ScrollDirection.Horizontal;
             ChromecastVersion = ChromecastVersion.Stable;
-            DashboardTheme = string.Empty;
-            TvHome = string.Empty;
 
             HomeSections = new HashSet<HomeSection>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="DisplayPreferences"/> class.
-        /// </summary>
-        protected DisplayPreferences()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the Id.
         /// </summary>
@@ -74,7 +65,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required. Max Length = 32.
         /// </remarks>
-        [Required]
         [MaxLength(32)]
         [StringLength(32)]
         public string Client { get; set; }
@@ -145,14 +135,14 @@ namespace Jellyfin.Data.Entities
         /// </summary>
         [MaxLength(32)]
         [StringLength(32)]
-        public string DashboardTheme { get; set; }
+        public string? DashboardTheme { get; set; }
 
         /// <summary>
         /// Gets or sets the tv home screen.
         /// </summary>
         [MaxLength(32)]
         [StringLength(32)]
-        public string TvHome { get; set; }
+        public string? TvHome { get; set; }
 
         /// <summary>
         /// Gets or sets the home sections.

+ 0 - 11
Jellyfin.Data/Entities/Group.cs

@@ -32,16 +32,6 @@ namespace Jellyfin.Data.Entities
             Preferences = new HashSet<Preference>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Group"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Group()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id of this group.
         /// </summary>
@@ -56,7 +46,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required, Max length = 255.
         /// </remarks>
-        [Required]
         [MaxLength(255)]
         [StringLength(255)]
         public string Name { get; set; }

+ 0 - 1
Jellyfin.Data/Entities/HomeSection.cs

@@ -15,7 +15,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Identity. Required.
         /// </remarks>
-        [Key]
         [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
         public int Id { get; protected set; }
 

+ 0 - 11
Jellyfin.Data/Entities/ImageInfo.cs

@@ -19,16 +19,6 @@ namespace Jellyfin.Data.Entities
             LastModified = DateTime.UtcNow;
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ImageInfo"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected ImageInfo()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
@@ -49,7 +39,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required.
         /// </remarks>
-        [Required]
         [MaxLength(512)]
         [StringLength(512)]
         public string Path { get; set; }

+ 0 - 9
Jellyfin.Data/Entities/ItemDisplayPreferences.cs

@@ -28,13 +28,6 @@ namespace Jellyfin.Data.Entities
             RememberIndexing = false;
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ItemDisplayPreferences"/> class.
-        /// </summary>
-        protected ItemDisplayPreferences()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the Id.
         /// </summary>
@@ -66,7 +59,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required. Max Length = 32.
         /// </remarks>
-        [Required]
         [MaxLength(32)]
         [StringLength(32)]
         public string Client { get; set; }
@@ -106,7 +98,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required.
         /// </remarks>
-        [Required]
         [MaxLength(64)]
         [StringLength(64)]
         public string SortBy { get; set; }

+ 1 - 15
Jellyfin.Data/Entities/Libraries/Artwork.cs

@@ -18,8 +18,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="path">The path.</param>
         /// <param name="kind">The kind of art.</param>
-        /// <param name="owner">The owner.</param>
-        public Artwork(string path, ArtKind kind, IHasArtwork owner)
+        public Artwork(string path, ArtKind kind)
         {
             if (string.IsNullOrEmpty(path))
             {
@@ -28,18 +27,6 @@ namespace Jellyfin.Data.Entities.Libraries
 
             Path = path;
             Kind = kind;
-
-            owner?.Artwork.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Artwork"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Artwork()
-        {
         }
 
         /// <summary>
@@ -57,7 +44,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Required, Max length = 65535.
         /// </remarks>
-        [Required]
         [MaxLength(65535)]
         [StringLength(65535)]
         public string Path { get; set; }

+ 2 - 1
Jellyfin.Data/Entities/Libraries/Book.cs

@@ -13,7 +13,8 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Initializes a new instance of the <see cref="Book"/> class.
         /// </summary>
-        public Book()
+        /// <param name="library">The library.</param>
+        public Book(Library library) : base(library)
         {
             BookMetadata = new HashSet<BookMetadata>();
             Releases = new HashSet<Release>();

+ 1 - 22
Jellyfin.Data/Entities/Libraries/BookMetadata.cs

@@ -1,8 +1,6 @@
 #pragma warning disable CA2227
 
-using System;
 using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations.Schema;
 using Jellyfin.Data.Interfaces;
 
 namespace Jellyfin.Data.Entities.Libraries
@@ -17,29 +15,11 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="title">The title or name of the object.</param>
         /// <param name="language">ISO-639-3 3-character language codes.</param>
-        /// <param name="book">The book.</param>
-        public BookMetadata(string title, string language, Book book) : base(title, language)
+        public BookMetadata(string title, string language) : base(title, language)
         {
-            if (book == null)
-            {
-                throw new ArgumentNullException(nameof(book));
-            }
-
-            book.BookMetadata.Add(this);
-
             Publishers = new HashSet<Company>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BookMetadata"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected BookMetadata()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the ISBN.
         /// </summary>
@@ -51,7 +31,6 @@ namespace Jellyfin.Data.Entities.Libraries
         public virtual ICollection<Company> Publishers { get; protected set; }
 
         /// <inheritdoc />
-        [NotMapped]
         public ICollection<Company> Companies => Publishers;
     }
 }

+ 2 - 21
Jellyfin.Data/Entities/Libraries/Chapter.cs

@@ -17,8 +17,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="language">ISO-639-3 3-character language codes.</param>
         /// <param name="startTime">The start time for this chapter.</param>
-        /// <param name="release">The release.</param>
-        public Chapter(string language, long startTime, Release release)
+        public Chapter(string language, long startTime)
         {
             if (string.IsNullOrEmpty(language))
             {
@@ -27,23 +26,6 @@ namespace Jellyfin.Data.Entities.Libraries
 
             Language = language;
             StartTime = startTime;
-
-            if (release == null)
-            {
-                throw new ArgumentNullException(nameof(release));
-            }
-
-            release.Chapters.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Chapter"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Chapter()
-        {
         }
 
         /// <summary>
@@ -63,7 +45,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Name { get; set; }
+        public string? Name { get; set; }
 
         /// <summary>
         /// Gets or sets the language.
@@ -72,7 +54,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// Required, Min length = 3, Max length = 3
         /// ISO-639-3 3-character language codes.
         /// </remarks>
-        [Required]
         [MinLength(3)]
         [MaxLength(3)]
         [StringLength(3)]

+ 1 - 1
Jellyfin.Data/Entities/Libraries/Collection.cs

@@ -38,7 +38,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Name { get; set; }
+        public string? Name { get; set; }
 
         /// <inheritdoc />
         [ConcurrencyCheck]

+ 5 - 35
Jellyfin.Data/Entities/Libraries/CollectionItem.cs

@@ -1,4 +1,3 @@
-using System;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
 using Jellyfin.Data.Interfaces;
@@ -13,39 +12,10 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Initializes a new instance of the <see cref="CollectionItem"/> class.
         /// </summary>
-        /// <param name="collection">The collection.</param>
-        /// <param name="previous">The previous item.</param>
-        /// <param name="next">The next item.</param>
-        public CollectionItem(Collection collection, CollectionItem previous, CollectionItem next)
-        {
-            if (collection == null)
-            {
-                throw new ArgumentNullException(nameof(collection));
-            }
-
-            collection.Items.Add(this);
-
-            if (next != null)
-            {
-                Next = next;
-                next.Previous = this;
-            }
-
-            if (previous != null)
-            {
-                Previous = previous;
-                previous.Next = this;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CollectionItem"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected CollectionItem()
+        /// <param name="libraryItem">The library item.</param>
+        public CollectionItem(LibraryItem libraryItem)
         {
+            LibraryItem = libraryItem;
         }
 
         /// <summary>
@@ -75,7 +45,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// TODO check if this properly updated Dependant and has the proper principal relationship.
         /// </remarks>
-        public virtual CollectionItem Next { get; set; }
+        public virtual CollectionItem? Next { get; set; }
 
         /// <summary>
         /// Gets or sets the previous item in the collection.
@@ -83,7 +53,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// TODO check if this properly updated Dependant and has the proper principal relationship.
         /// </remarks>
-        public virtual CollectionItem Previous { get; set; }
+        public virtual CollectionItem? Previous { get; set; }
 
         /// <inheritdoc />
         public void OnSavingChanges()

+ 2 - 15
Jellyfin.Data/Entities/Libraries/Company.cs

@@ -15,22 +15,10 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Initializes a new instance of the <see cref="Company"/> class.
         /// </summary>
-        /// <param name="owner">The owner of this company.</param>
-        public Company(IHasCompanies owner)
+        public Company()
         {
-            owner?.Companies.Add(this);
-
             CompanyMetadata = new HashSet<CompanyMetadata>();
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Company"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Company()
-        {
+            ChildCompanies = new HashSet<Company>();
         }
 
         /// <summary>
@@ -57,7 +45,6 @@ namespace Jellyfin.Data.Entities.Libraries
         public virtual ICollection<Company> ChildCompanies { get; protected set; }
 
         /// <inheritdoc />
-        [NotMapped]
         public ICollection<Company> Companies => ChildCompanies;
 
         /// <inheritdoc />

+ 5 - 20
Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs

@@ -1,4 +1,3 @@
-using System;
 using System.ComponentModel.DataAnnotations;
 
 namespace Jellyfin.Data.Entities.Libraries
@@ -13,21 +12,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="title">The title or name of the object.</param>
         /// <param name="language">ISO-639-3 3-character language codes.</param>
-        /// <param name="company">The company.</param>
-        public CompanyMetadata(string title, string language, Company company) : base(title, language)
-        {
-            if (company == null)
-            {
-                throw new ArgumentNullException(nameof(company));
-            }
-
-            company.CompanyMetadata.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CompanyMetadata"/> class.
-        /// </summary>
-        protected CompanyMetadata()
+        public CompanyMetadata(string title, string language) : base(title, language)
         {
         }
 
@@ -39,7 +24,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(65535)]
         [StringLength(65535)]
-        public string Description { get; set; }
+        public string? Description { get; set; }
 
         /// <summary>
         /// Gets or sets the headquarters.
@@ -49,7 +34,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(255)]
         [StringLength(255)]
-        public string Headquarters { get; set; }
+        public string? Headquarters { get; set; }
 
         /// <summary>
         /// Gets or sets the country code.
@@ -59,7 +44,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(2)]
         [StringLength(2)]
-        public string Country { get; set; }
+        public string? Country { get; set; }
 
         /// <summary>
         /// Gets or sets the homepage.
@@ -69,6 +54,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Homepage { get; set; }
+        public string? Homepage { get; set; }
     }
 }

+ 2 - 1
Jellyfin.Data/Entities/Libraries/CustomItem.cs

@@ -13,7 +13,8 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Initializes a new instance of the <see cref="CustomItem"/> class.
         /// </summary>
-        public CustomItem()
+        /// <param name="library">The library.</param>
+        public CustomItem(Library library) : base(library)
         {
             CustomItemMetadata = new HashSet<CustomItemMetadata>();
             Releases = new HashSet<Release>();

+ 1 - 20
Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs

@@ -1,5 +1,3 @@
-using System;
-
 namespace Jellyfin.Data.Entities.Libraries
 {
     /// <summary>
@@ -12,24 +10,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="title">The title or name of the object.</param>
         /// <param name="language">ISO-639-3 3-character language codes.</param>
-        /// <param name="item">The item.</param>
-        public CustomItemMetadata(string title, string language, CustomItem item) : base(title, language)
-        {
-            if (item == null)
-            {
-                throw new ArgumentNullException(nameof(item));
-            }
-
-            item.CustomItemMetadata.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CustomItemMetadata"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected CustomItemMetadata()
+        public CustomItemMetadata(string title, string language) : base(title, language)
         {
         }
     }

+ 2 - 20
Jellyfin.Data/Entities/Libraries/Episode.cs

@@ -1,6 +1,5 @@
 #pragma warning disable CA2227
 
-using System;
 using System.Collections.Generic;
 using Jellyfin.Data.Interfaces;
 
@@ -14,30 +13,13 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Initializes a new instance of the <see cref="Episode"/> class.
         /// </summary>
-        /// <param name="season">The season.</param>
-        public Episode(Season season)
+        /// <param name="library">The library.</param>
+        public Episode(Library library) : base(library)
         {
-            if (season == null)
-            {
-                throw new ArgumentNullException(nameof(season));
-            }
-
-            season.Episodes.Add(this);
-
             Releases = new HashSet<Release>();
             EpisodeMetadata = new HashSet<EpisodeMetadata>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Episode"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Episode()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the episode number.
         /// </summary>

+ 4 - 22
Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs

@@ -1,4 +1,3 @@
-using System;
 using System.ComponentModel.DataAnnotations;
 
 namespace Jellyfin.Data.Entities.Libraries
@@ -13,24 +12,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="title">The title or name of the object.</param>
         /// <param name="language">ISO-639-3 3-character language codes.</param>
-        /// <param name="episode">The episode.</param>
-        public EpisodeMetadata(string title, string language, Episode episode) : base(title, language)
-        {
-            if (episode == null)
-            {
-                throw new ArgumentNullException(nameof(episode));
-            }
-
-            episode.EpisodeMetadata.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="EpisodeMetadata"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected EpisodeMetadata()
+        public EpisodeMetadata(string title, string language) : base(title, language)
         {
         }
 
@@ -42,7 +24,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Outline { get; set; }
+        public string? Outline { get; set; }
 
         /// <summary>
         /// Gets or sets the plot.
@@ -52,7 +34,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(65535)]
         [StringLength(65535)]
-        public string Plot { get; set; }
+        public string? Plot { get; set; }
 
         /// <summary>
         /// Gets or sets the tagline.
@@ -62,6 +44,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Tagline { get; set; }
+        public string? Tagline { get; set; }
     }
 }

+ 1 - 26
Jellyfin.Data/Entities/Libraries/Genre.cs

@@ -1,4 +1,3 @@
-using System;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
 using Jellyfin.Data.Interfaces;
@@ -14,32 +13,9 @@ namespace Jellyfin.Data.Entities.Libraries
         /// Initializes a new instance of the <see cref="Genre"/> class.
         /// </summary>
         /// <param name="name">The name.</param>
-        /// <param name="itemMetadata">The metadata.</param>
-        public Genre(string name, ItemMetadata itemMetadata)
+        public Genre(string name)
         {
-            if (string.IsNullOrEmpty(name))
-            {
-                throw new ArgumentNullException(nameof(name));
-            }
-
             Name = name;
-
-            if (itemMetadata == null)
-            {
-                throw new ArgumentNullException(nameof(itemMetadata));
-            }
-
-            itemMetadata.Genres.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Genre"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Genre()
-        {
         }
 
         /// <summary>
@@ -57,7 +33,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Indexed, Required, Max length = 255.
         /// </remarks>
-        [Required]
         [MaxLength(255)]
         [StringLength(255)]
         public string Name { get; set; }

+ 2 - 14
Jellyfin.Data/Entities/Libraries/ItemMetadata.cs

@@ -42,16 +42,6 @@ namespace Jellyfin.Data.Entities.Libraries
             Sources = new HashSet<MetadataProviderId>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ItemMetadata"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to being abstract.
-        /// </remarks>
-        protected ItemMetadata()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
@@ -67,7 +57,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Required, Max length = 1024.
         /// </remarks>
-        [Required]
         [MaxLength(1024)]
         [StringLength(1024)]
         public string Title { get; set; }
@@ -80,7 +69,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string OriginalTitle { get; set; }
+        public string? OriginalTitle { get; set; }
 
         /// <summary>
         /// Gets or sets the sort title.
@@ -90,7 +79,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string SortTitle { get; set; }
+        public string? SortTitle { get; set; }
 
         /// <summary>
         /// Gets or sets the language.
@@ -99,7 +88,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// Required, Min length = 3, Max length = 3.
         /// ISO-639-3 3-character language codes.
         /// </remarks>
-        [Required]
         [MinLength(3)]
         [MaxLength(3)]
         [StringLength(3)]

+ 3 - 19
Jellyfin.Data/Entities/Libraries/Library.cs

@@ -1,4 +1,3 @@
-using System;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
 using Jellyfin.Data.Interfaces;
@@ -14,24 +13,11 @@ namespace Jellyfin.Data.Entities.Libraries
         /// Initializes a new instance of the <see cref="Library"/> class.
         /// </summary>
         /// <param name="name">The name of the library.</param>
-        public Library(string name)
+        /// <param name="path">The path of the library.</param>
+        public Library(string name, string path)
         {
-            if (string.IsNullOrWhiteSpace(name))
-            {
-                throw new ArgumentNullException(nameof(name));
-            }
-
             Name = name;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Library"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Library()
-        {
+            Path = path;
         }
 
         /// <summary>
@@ -49,7 +35,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Required, Max length = 128.
         /// </remarks>
-        [Required]
         [MaxLength(128)]
         [StringLength(128)]
         public string Name { get; set; }
@@ -60,7 +45,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Required.
         /// </remarks>
-        [Required]
         public string Path { get; set; }
 
         /// <inheritdoc />

+ 0 - 8
Jellyfin.Data/Entities/Libraries/LibraryItem.cs

@@ -20,13 +20,6 @@ namespace Jellyfin.Data.Entities.Libraries
             Library = library;
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="LibraryItem"/> class.
-        /// </summary>
-        protected LibraryItem()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
@@ -51,7 +44,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Required.
         /// </remarks>
-        [Required]
         public virtual Library Library { get; set; }
 
         /// <inheritdoc />

+ 1 - 20
Jellyfin.Data/Entities/Libraries/MediaFile.cs

@@ -19,8 +19,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="path">The path relative to the LibraryRoot.</param>
         /// <param name="kind">The file kind.</param>
-        /// <param name="release">The release.</param>
-        public MediaFile(string path, MediaFileKind kind, Release release)
+        public MediaFile(string path, MediaFileKind kind)
         {
             if (string.IsNullOrEmpty(path))
             {
@@ -30,26 +29,9 @@ namespace Jellyfin.Data.Entities.Libraries
             Path = path;
             Kind = kind;
 
-            if (release == null)
-            {
-                throw new ArgumentNullException(nameof(release));
-            }
-
-            release.MediaFiles.Add(this);
-
             MediaFileStreams = new HashSet<MediaFileStream>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="MediaFile"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected MediaFile()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
@@ -65,7 +47,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Required, Max length = 65535.
         /// </remarks>
-        [Required]
         [MaxLength(65535)]
         [StringLength(65535)]
         public string Path { get; set; }

+ 1 - 20
Jellyfin.Data/Entities/Libraries/MediaFileStream.cs

@@ -1,6 +1,5 @@
 #pragma warning disable CA1711 // Identifiers should not have incorrect suffix
 
-using System;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
 using Jellyfin.Data.Interfaces;
@@ -16,27 +15,9 @@ namespace Jellyfin.Data.Entities.Libraries
         /// Initializes a new instance of the <see cref="MediaFileStream"/> class.
         /// </summary>
         /// <param name="streamNumber">The number of this stream.</param>
-        /// <param name="mediaFile">The media file.</param>
-        public MediaFileStream(int streamNumber, MediaFile mediaFile)
+        public MediaFileStream(int streamNumber)
         {
             StreamNumber = streamNumber;
-
-            if (mediaFile == null)
-            {
-                throw new ArgumentNullException(nameof(mediaFile));
-            }
-
-            mediaFile.MediaFileStreams.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="MediaFileStream"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected MediaFileStream()
-        {
         }
 
         /// <summary>

+ 0 - 11
Jellyfin.Data/Entities/Libraries/MetadataProvider.cs

@@ -24,16 +24,6 @@ namespace Jellyfin.Data.Entities.Libraries
             Name = name;
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="MetadataProvider"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected MetadataProvider()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
@@ -49,7 +39,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Required, Max length = 1024.
         /// </remarks>
-        [Required]
         [MaxLength(1024)]
         [StringLength(1024)]
         public string Name { get; set; }

+ 3 - 20
Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs

@@ -14,8 +14,8 @@ namespace Jellyfin.Data.Entities.Libraries
         /// Initializes a new instance of the <see cref="MetadataProviderId"/> class.
         /// </summary>
         /// <param name="providerId">The provider id.</param>
-        /// <param name="itemMetadata">The metadata entity.</param>
-        public MetadataProviderId(string providerId, ItemMetadata itemMetadata)
+        /// <param name="metadataProvider">The metadata provider.</param>
+        public MetadataProviderId(string providerId, MetadataProvider metadataProvider)
         {
             if (string.IsNullOrEmpty(providerId))
             {
@@ -23,23 +23,7 @@ namespace Jellyfin.Data.Entities.Libraries
             }
 
             ProviderId = providerId;
-
-            if (itemMetadata == null)
-            {
-                throw new ArgumentNullException(nameof(itemMetadata));
-            }
-
-            itemMetadata.Sources.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="MetadataProviderId"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected MetadataProviderId()
-        {
+            MetadataProvider = metadataProvider;
         }
 
         /// <summary>
@@ -57,7 +41,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Required, Max length = 255.
         /// </remarks>
-        [Required]
         [MaxLength(255)]
         [StringLength(255)]
         public string ProviderId { get; set; }

+ 2 - 1
Jellyfin.Data/Entities/Libraries/Movie.cs

@@ -13,7 +13,8 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Initializes a new instance of the <see cref="Movie"/> class.
         /// </summary>
-        public Movie()
+        /// <param name="library">The library.</param>
+        public Movie(Library library) : base(library)
         {
             Releases = new HashSet<Release>();
             MovieMetadata = new HashSet<MovieMetadata>();

+ 5 - 20
Jellyfin.Data/Entities/Libraries/MovieMetadata.cs

@@ -2,7 +2,6 @@
 
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
 using Jellyfin.Data.Interfaces;
 
 namespace Jellyfin.Data.Entities.Libraries
@@ -17,22 +16,9 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="title">The title or name of the movie.</param>
         /// <param name="language">ISO-639-3 3-character language codes.</param>
-        /// <param name="movie">The movie.</param>
-        public MovieMetadata(string title, string language, Movie movie) : base(title, language)
+        public MovieMetadata(string title, string language) : base(title, language)
         {
             Studios = new HashSet<Company>();
-
-            movie.MovieMetadata.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="MovieMetadata"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected MovieMetadata()
-        {
         }
 
         /// <summary>
@@ -43,7 +29,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Outline { get; set; }
+        public string? Outline { get; set; }
 
         /// <summary>
         /// Gets or sets the tagline.
@@ -53,7 +39,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Tagline { get; set; }
+        public string? Tagline { get; set; }
 
         /// <summary>
         /// Gets or sets the plot.
@@ -63,7 +49,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(65535)]
         [StringLength(65535)]
-        public string Plot { get; set; }
+        public string? Plot { get; set; }
 
         /// <summary>
         /// Gets or sets the country code.
@@ -73,7 +59,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(2)]
         [StringLength(2)]
-        public string Country { get; set; }
+        public string? Country { get; set; }
 
         /// <summary>
         /// Gets or sets the studios that produced this movie.
@@ -81,7 +67,6 @@ namespace Jellyfin.Data.Entities.Libraries
         public virtual ICollection<Company> Studios { get; protected set; }
 
         /// <inheritdoc />
-        [NotMapped]
         public ICollection<Company> Companies => Studios;
     }
 }

+ 2 - 1
Jellyfin.Data/Entities/Libraries/MusicAlbum.cs

@@ -12,7 +12,8 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Initializes a new instance of the <see cref="MusicAlbum"/> class.
         /// </summary>
-        public MusicAlbum()
+        /// <param name="library">The library.</param>
+        public MusicAlbum(Library library) : base(library)
         {
             MusicAlbumMetadata = new HashSet<MusicAlbumMetadata>();
             Tracks = new HashSet<Track>();

+ 4 - 17
Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs

@@ -15,22 +15,9 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="title">The title or name of the album.</param>
         /// <param name="language">ISO-639-3 3-character language codes.</param>
-        /// <param name="album">The music album.</param>
-        public MusicAlbumMetadata(string title, string language, MusicAlbum album) : base(title, language)
+        public MusicAlbumMetadata(string title, string language) : base(title, language)
         {
             Labels = new HashSet<Company>();
-
-            album.MusicAlbumMetadata.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="MusicAlbumMetadata"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected MusicAlbumMetadata()
-        {
         }
 
         /// <summary>
@@ -41,7 +28,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(255)]
         [StringLength(255)]
-        public string Barcode { get; set; }
+        public string? Barcode { get; set; }
 
         /// <summary>
         /// Gets or sets the label number.
@@ -51,7 +38,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(255)]
         [StringLength(255)]
-        public string LabelNumber { get; set; }
+        public string? LabelNumber { get; set; }
 
         /// <summary>
         /// Gets or sets the country code.
@@ -61,7 +48,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(2)]
         [StringLength(2)]
-        public string Country { get; set; }
+        public string? Country { get; set; }
 
         /// <summary>
         /// Gets or sets a collection containing the labels.

+ 1 - 12
Jellyfin.Data/Entities/Libraries/Person.cs

@@ -31,16 +31,6 @@ namespace Jellyfin.Data.Entities.Libraries
             Sources = new HashSet<MetadataProviderId>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Person"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Person()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
@@ -56,7 +46,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Required, Max length = 1024.
         /// </remarks>
-        [Required]
         [MaxLength(1024)]
         [StringLength(1024)]
         public string Name { get; set; }
@@ -69,7 +58,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(256)]
         [StringLength(256)]
-        public string SourceId { get; set; }
+        public string? SourceId { get; set; }
 
         /// <summary>
         /// Gets or sets the date added.

+ 5 - 23
Jellyfin.Data/Entities/Libraries/PersonRole.cs

@@ -1,6 +1,5 @@
 #pragma warning disable CA2227
 
-using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
@@ -18,31 +17,15 @@ namespace Jellyfin.Data.Entities.Libraries
         /// Initializes a new instance of the <see cref="PersonRole"/> class.
         /// </summary>
         /// <param name="type">The role type.</param>
-        /// <param name="itemMetadata">The metadata.</param>
-        public PersonRole(PersonRoleType type, ItemMetadata itemMetadata)
+        /// <param name="person">The person.</param>
+        public PersonRole(PersonRoleType type, Person person)
         {
             Type = type;
-
-            if (itemMetadata == null)
-            {
-                throw new ArgumentNullException(nameof(itemMetadata));
-            }
-
-            itemMetadata.PersonRoles.Add(this);
-
+            Person = person;
+            Artwork = new HashSet<Artwork>();
             Sources = new HashSet<MetadataProviderId>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="PersonRole"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected PersonRole()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
@@ -60,7 +43,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Role { get; set; }
+        public string? Role { get; set; }
 
         /// <summary>
         /// Gets or sets the person's role type.
@@ -80,7 +63,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Required.
         /// </remarks>
-        [Required]
         public virtual Person Person { get; set; }
 
         /// <inheritdoc />

+ 2 - 1
Jellyfin.Data/Entities/Libraries/Photo.cs

@@ -13,7 +13,8 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Initializes a new instance of the <see cref="Photo"/> class.
         /// </summary>
-        public Photo()
+        /// <param name="library">The library.</param>
+        public Photo(Library library) : base(library)
         {
             PhotoMetadata = new HashSet<PhotoMetadata>();
             Releases = new HashSet<Release>();

+ 1 - 20
Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs

@@ -1,5 +1,3 @@
-using System;
-
 namespace Jellyfin.Data.Entities.Libraries
 {
     /// <summary>
@@ -12,24 +10,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="title">The title or name of the photo.</param>
         /// <param name="language">ISO-639-3 3-character language codes.</param>
-        /// <param name="photo">The photo.</param>
-        public PhotoMetadata(string title, string language, Photo photo) : base(title, language)
-        {
-            if (photo == null)
-            {
-                throw new ArgumentNullException(nameof(photo));
-            }
-
-            photo.PhotoMetadata.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="PhotoMetadata"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected PhotoMetadata()
+        public PhotoMetadata(string title, string language) : base(title, language)
         {
         }
     }

+ 2 - 21
Jellyfin.Data/Entities/Libraries/Rating.cs

@@ -1,4 +1,3 @@
-using System;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
 using Jellyfin.Data.Interfaces;
@@ -14,27 +13,9 @@ namespace Jellyfin.Data.Entities.Libraries
         /// Initializes a new instance of the <see cref="Rating"/> class.
         /// </summary>
         /// <param name="value">The value.</param>
-        /// <param name="itemMetadata">The metadata.</param>
-        public Rating(double value, ItemMetadata itemMetadata)
+        public Rating(double value)
         {
             Value = value;
-
-            if (itemMetadata == null)
-            {
-                throw new ArgumentNullException(nameof(itemMetadata));
-            }
-
-            itemMetadata.Ratings.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Rating"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Rating()
-        {
         }
 
         /// <summary>
@@ -67,7 +48,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// Gets or sets the rating type.
         /// If this is <c>null</c> it's the internal user rating.
         /// </summary>
-        public virtual RatingSource RatingType { get; set; }
+        public virtual RatingSource? RatingType { get; set; }
 
         /// <inheritdoc />
         public void OnSavingChanges()

+ 3 - 22
Jellyfin.Data/Entities/Libraries/RatingSource.cs

@@ -1,4 +1,3 @@
-using System;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
 using Jellyfin.Data.Interfaces;
@@ -15,28 +14,10 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="minimumValue">The minimum value.</param>
         /// <param name="maximumValue">The maximum value.</param>
-        /// <param name="rating">The rating.</param>
-        public RatingSource(double minimumValue, double maximumValue, Rating rating)
+        public RatingSource(double minimumValue, double maximumValue)
         {
             MinimumValue = minimumValue;
             MaximumValue = maximumValue;
-
-            if (rating == null)
-            {
-                throw new ArgumentNullException(nameof(rating));
-            }
-
-            rating.RatingType = this;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RatingSource"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected RatingSource()
-        {
         }
 
         /// <summary>
@@ -56,7 +37,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Name { get; set; }
+        public string? Name { get; set; }
 
         /// <summary>
         /// Gets or sets the minimum value.
@@ -81,7 +62,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Gets or sets the metadata source.
         /// </summary>
-        public virtual MetadataProviderId Source { get; set; }
+        public virtual MetadataProviderId? Source { get; set; }
 
         /// <inheritdoc />
         public void OnSavingChanges()

+ 1 - 15
Jellyfin.Data/Entities/Libraries/Release.cs

@@ -17,8 +17,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// Initializes a new instance of the <see cref="Release"/> class.
         /// </summary>
         /// <param name="name">The name of this release.</param>
-        /// <param name="owner">The owner of this release.</param>
-        public Release(string name, IHasReleases owner)
+        public Release(string name)
         {
             if (string.IsNullOrEmpty(name))
             {
@@ -27,22 +26,10 @@ namespace Jellyfin.Data.Entities.Libraries
 
             Name = name;
 
-            owner?.Releases.Add(this);
-
             MediaFiles = new HashSet<MediaFile>();
             Chapters = new HashSet<Chapter>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Release"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Release()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
@@ -58,7 +45,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <remarks>
         /// Required, Max length = 1024.
         /// </remarks>
-        [Required]
         [MaxLength(1024)]
         [StringLength(1024)]
         public string Name { get; set; }

+ 2 - 20
Jellyfin.Data/Entities/Libraries/Season.cs

@@ -1,6 +1,5 @@
 #pragma warning disable CA2227
 
-using System;
 using System.Collections.Generic;
 
 namespace Jellyfin.Data.Entities.Libraries
@@ -13,30 +12,13 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Initializes a new instance of the <see cref="Season"/> class.
         /// </summary>
-        /// <param name="series">The series.</param>
-        public Season(Series series)
+        /// <param name="library">The library.</param>
+        public Season(Library library) : base(library)
         {
-            if (series == null)
-            {
-                throw new ArgumentNullException(nameof(series));
-            }
-
-            series.Seasons.Add(this);
-
             Episodes = new HashSet<Episode>();
             SeasonMetadata = new HashSet<SeasonMetadata>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Season"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Season()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the season number.
         /// </summary>

+ 2 - 20
Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs

@@ -1,4 +1,3 @@
-using System;
 using System.ComponentModel.DataAnnotations;
 
 namespace Jellyfin.Data.Entities.Libraries
@@ -13,24 +12,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="title">The title or name of the object.</param>
         /// <param name="language">ISO-639-3 3-character language codes.</param>
-        /// <param name="season">The season.</param>
-        public SeasonMetadata(string title, string language, Season season) : base(title, language)
-        {
-            if (season == null)
-            {
-                throw new ArgumentNullException(nameof(season));
-            }
-
-            season.SeasonMetadata.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SeasonMetadata"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected SeasonMetadata()
+        public SeasonMetadata(string title, string language) : base(title, language)
         {
         }
 
@@ -42,6 +24,6 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Outline { get; set; }
+        public string? Outline { get; set; }
     }
 }

+ 2 - 1
Jellyfin.Data/Entities/Libraries/Series.cs

@@ -13,7 +13,8 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Initializes a new instance of the <see cref="Series"/> class.
         /// </summary>
-        public Series()
+        /// <param name="library">The library.</param>
+        public Series(Library library) : base(library)
         {
             DateAdded = DateTime.UtcNow;
             Seasons = new HashSet<Season>();

+ 5 - 25
Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs

@@ -1,6 +1,5 @@
 #pragma warning disable CA2227
 
-using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
@@ -18,29 +17,11 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="title">The title or name of the object.</param>
         /// <param name="language">ISO-639-3 3-character language codes.</param>
-        /// <param name="series">The series.</param>
-        public SeriesMetadata(string title, string language, Series series) : base(title, language)
+        public SeriesMetadata(string title, string language) : base(title, language)
         {
-            if (series == null)
-            {
-                throw new ArgumentNullException(nameof(series));
-            }
-
-            series.SeriesMetadata.Add(this);
-
             Networks = new HashSet<Company>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SeriesMetadata"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected SeriesMetadata()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the outline.
         /// </summary>
@@ -49,7 +30,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Outline { get; set; }
+        public string? Outline { get; set; }
 
         /// <summary>
         /// Gets or sets the plot.
@@ -59,7 +40,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(65535)]
         [StringLength(65535)]
-        public string Plot { get; set; }
+        public string? Plot { get; set; }
 
         /// <summary>
         /// Gets or sets the tagline.
@@ -69,7 +50,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(1024)]
         [StringLength(1024)]
-        public string Tagline { get; set; }
+        public string? Tagline { get; set; }
 
         /// <summary>
         /// Gets or sets the country code.
@@ -79,7 +60,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </remarks>
         [MaxLength(2)]
         [StringLength(2)]
-        public string Country { get; set; }
+        public string? Country { get; set; }
 
         /// <summary>
         /// Gets or sets a collection containing the networks.
@@ -87,7 +68,6 @@ namespace Jellyfin.Data.Entities.Libraries
         public virtual ICollection<Company> Networks { get; protected set; }
 
         /// <inheritdoc />
-        [NotMapped]
         public ICollection<Company> Companies => Networks;
     }
 }

+ 2 - 20
Jellyfin.Data/Entities/Libraries/Track.cs

@@ -1,6 +1,5 @@
 #pragma warning disable CA2227
 
-using System;
 using System.Collections.Generic;
 using Jellyfin.Data.Interfaces;
 
@@ -14,30 +13,13 @@ namespace Jellyfin.Data.Entities.Libraries
         /// <summary>
         /// Initializes a new instance of the <see cref="Track"/> class.
         /// </summary>
-        /// <param name="album">The album.</param>
-        public Track(MusicAlbum album)
+        /// <param name="library">The library.</param>
+        public Track(Library library) : base(library)
         {
-            if (album == null)
-            {
-                throw new ArgumentNullException(nameof(album));
-            }
-
-            album.Tracks.Add(this);
-
             Releases = new HashSet<Release>();
             TrackMetadata = new HashSet<TrackMetadata>();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Track"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected Track()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the track number.
         /// </summary>

+ 1 - 20
Jellyfin.Data/Entities/Libraries/TrackMetadata.cs

@@ -1,5 +1,3 @@
-using System;
-
 namespace Jellyfin.Data.Entities.Libraries
 {
     /// <summary>
@@ -12,24 +10,7 @@ namespace Jellyfin.Data.Entities.Libraries
         /// </summary>
         /// <param name="title">The title or name of the object.</param>
         /// <param name="language">ISO-639-3 3-character language codes.</param>
-        /// <param name="track">The track.</param>
-        public TrackMetadata(string title, string language, Track track) : base(title, language)
-        {
-            if (track == null)
-            {
-                throw new ArgumentNullException(nameof(track));
-            }
-
-            track.TrackMetadata.Add(this);
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="TrackMetadata"/> class.
-        /// </summary>
-        /// <remarks>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </remarks>
-        protected TrackMetadata()
+        public TrackMetadata(string title, string language) : base(title, language)
         {
         }
     }

+ 0 - 8
Jellyfin.Data/Entities/Permission.cs

@@ -24,14 +24,6 @@ namespace Jellyfin.Data.Entities
             Value = value;
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Permission"/> class.
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </summary>
-        protected Permission()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id of this permission.
         /// </summary>

+ 0 - 9
Jellyfin.Data/Entities/Preference.cs

@@ -23,14 +23,6 @@ namespace Jellyfin.Data.Entities
             Value = value ?? throw new ArgumentNullException(nameof(value));
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="Preference"/> class.
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </summary>
-        protected Preference()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the id of this preference.
         /// </summary>
@@ -54,7 +46,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required, Max length = 65535.
         /// </remarks>
-        [Required]
         [MaxLength(65535)]
         [StringLength(65535)]
         public string Value { get; set; }

+ 7 - 18
Jellyfin.Data/Entities/User.cs

@@ -51,6 +51,7 @@ namespace Jellyfin.Data.Entities
             PasswordResetProviderId = passwordResetProviderId;
 
             AccessSchedules = new HashSet<AccessSchedule>();
+            DisplayPreferences = new HashSet<DisplayPreferences>();
             ItemDisplayPreferences = new HashSet<ItemDisplayPreferences>();
             // Groups = new HashSet<Group>();
             Permissions = new HashSet<Permission>();
@@ -77,14 +78,6 @@ namespace Jellyfin.Data.Entities
             AddDefaultPreferences();
         }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="User"/> class.
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </summary>
-        protected User()
-        {
-        }
-
         /// <summary>
         /// Gets or sets the Id of the user.
         /// </summary>
@@ -100,7 +93,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required, Max length = 255.
         /// </remarks>
-        [Required]
         [MaxLength(255)]
         [StringLength(255)]
         public string Username { get; set; }
@@ -113,7 +105,7 @@ namespace Jellyfin.Data.Entities
         /// </remarks>
         [MaxLength(65535)]
         [StringLength(65535)]
-        public string Password { get; set; }
+        public string? Password { get; set; }
 
         /// <summary>
         /// Gets or sets the user's easy password, or <c>null</c> if none is set.
@@ -123,7 +115,7 @@ namespace Jellyfin.Data.Entities
         /// </remarks>
         [MaxLength(65535)]
         [StringLength(65535)]
-        public string EasyPassword { get; set; }
+        public string? EasyPassword { get; set; }
 
         /// <summary>
         /// Gets or sets a value indicating whether the user must update their password.
@@ -141,7 +133,7 @@ namespace Jellyfin.Data.Entities
         /// </remarks>
         [MaxLength(255)]
         [StringLength(255)]
-        public string AudioLanguagePreference { get; set; }
+        public string? AudioLanguagePreference { get; set; }
 
         /// <summary>
         /// Gets or sets the authentication provider id.
@@ -149,7 +141,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required, Max length = 255.
         /// </remarks>
-        [Required]
         [MaxLength(255)]
         [StringLength(255)]
         public string AuthenticationProviderId { get; set; }
@@ -160,7 +151,6 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required, Max length = 255.
         /// </remarks>
-        [Required]
         [MaxLength(255)]
         [StringLength(255)]
         public string PasswordResetProviderId { get; set; }
@@ -217,7 +207,7 @@ namespace Jellyfin.Data.Entities
         /// </remarks>
         [MaxLength(255)]
         [StringLength(255)]
-        public string SubtitleLanguagePreference { get; set; }
+        public string? SubtitleLanguagePreference { get; set; }
 
         /// <summary>
         /// Gets or sets a value indicating whether missing episodes should be displayed.
@@ -312,7 +302,7 @@ namespace Jellyfin.Data.Entities
         /// Gets or sets the user's profile image. Can be <c>null</c>.
         /// </summary>
         // [ForeignKey("UserId")]
-        public virtual ImageInfo ProfileImage { get; set; }
+        public virtual ImageInfo? ProfileImage { get; set; }
 
         /// <summary>
         /// Gets or sets the user's display preferences.
@@ -320,8 +310,7 @@ namespace Jellyfin.Data.Entities
         /// <remarks>
         /// Required.
         /// </remarks>
-        [Required]
-        public virtual DisplayPreferences DisplayPreferences { get; set; }
+        public virtual ICollection<DisplayPreferences> DisplayPreferences { get; set; }
 
         /// <summary>
         /// Gets or sets the level of sync play permissions this user has.

+ 1 - 1
Jellyfin.Data/Interfaces/IHasPermissions.cs

@@ -2,7 +2,7 @@
 using Jellyfin.Data.Entities;
 using Jellyfin.Data.Enums;
 
-namespace Jellyfin.Data
+namespace Jellyfin.Data.Interfaces
 {
     /// <summary>
     /// An abstraction representing an entity that has permissions.

+ 2 - 2
Jellyfin.Data/Jellyfin.Data.csproj

@@ -7,6 +7,7 @@
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <AnalysisMode>AllEnabledByDefault</AnalysisMode>
     <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
+    <Nullable>enable</Nullable>
     <PublishRepositoryUrl>true</PublishRepositoryUrl>
     <EmbedUntrackedSources>true</EmbedUntrackedSources>
     <IncludeSymbols>true</IncludeSymbols>
@@ -38,8 +39,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.3" />
-    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.3" />
+    <PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
   </ItemGroup>
 
   <ItemGroup>

+ 2 - 2
Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs

@@ -86,7 +86,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Session
             return name;
         }
 
-        private static string? GetPlaybackNotificationType(string mediaType)
+        private static string GetPlaybackNotificationType(string mediaType)
         {
             if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
             {
@@ -98,7 +98,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Session
                 return NotificationType.VideoPlayback.ToString();
             }
 
-            return null;
+            return "Playback";
         }
     }
 }

+ 2 - 0
Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj

@@ -27,6 +27,8 @@
 
   <ItemGroup>
     <PackageReference Include="System.Linq.Async" Version="5.0.0" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.3" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.3" />
     <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.3">
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

+ 3 - 3
Jellyfin.Server.Implementations/Users/UserManager.cs

@@ -184,8 +184,8 @@ namespace Jellyfin.Server.Implementations.Users
 
             var user = new User(
                 name,
-                _defaultAuthenticationProvider.GetType().FullName,
-                _defaultPasswordResetProvider.GetType().FullName)
+                _defaultAuthenticationProvider.GetType().FullName!,
+                _defaultPasswordResetProvider.GetType().FullName!)
             {
                 InternalId = max + 1
             };
@@ -444,7 +444,7 @@ namespace Jellyfin.Server.Implementations.Users
             {
                 var providerId = authenticationProvider.GetType().FullName;
 
-                if (!string.Equals(providerId, user.AuthenticationProviderId, StringComparison.OrdinalIgnoreCase))
+                if (providerId != null && !string.Equals(providerId, user.AuthenticationProviderId, StringComparison.OrdinalIgnoreCase))
                 {
                     user.AuthenticationProviderId = providerId;
                     await UpdateUserAsync(user).ConfigureAwait(false);

+ 1 - 3
Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs

@@ -1,7 +1,5 @@
 using System;
-using System.Globalization;
 using System.IO;
-using System.Linq;
 using Emby.Server.Implementations.Data;
 using Emby.Server.Implementations.Serialization;
 using Jellyfin.Data.Entities;
@@ -104,7 +102,7 @@ namespace Jellyfin.Server.Migrations.Routines
                         _ => policy.LoginAttemptsBeforeLockout
                     };
 
-                    var user = new User(mockup.Name, policy.AuthenticationProviderId, policy.PasswordResetProviderId)
+                    var user = new User(mockup.Name, policy.AuthenticationProviderId!, policy.PasswordResetProviderId!)
                     {
                         Id = entry[1].ReadGuidFromBlob(),
                         InternalId = entry[0].ToInt64(),

+ 1 - 1
MediaBrowser.Controller/Drawing/IImageProcessor.cs

@@ -61,7 +61,7 @@ namespace MediaBrowser.Controller.Drawing
 
         string GetImageCacheTag(BaseItem item, ChapterInfo info);
 
-        string GetImageCacheTag(User user);
+        string? GetImageCacheTag(User user);
 
         /// <summary>
         /// Processes the image.

+ 2 - 2
tests/Jellyfin.Api.Tests/TestHelpers.cs

@@ -26,8 +26,8 @@ namespace Jellyfin.Api.Tests
         {
             var user = new User(
                 "jellyfin",
-                typeof(DefaultAuthenticationProvider).FullName,
-                typeof(DefaultPasswordResetProvider).FullName);
+                typeof(DefaultAuthenticationProvider).FullName!,
+                typeof(DefaultPasswordResetProvider).FullName!);
 
             // Set administrator flag.
             user.SetPermission(PermissionKind.IsAdministrator, role.Equals(UserRoles.Administrator, StringComparison.OrdinalIgnoreCase));