aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration
diff options
context:
space:
mode:
authorJPVenson <github@jpb.email>2025-01-26 20:45:28 +0000
committerJPVenson <github@jpb.email>2025-01-26 20:45:28 +0000
commitaa811eb1e3c78bdf8f4a751311c1bb6d639e851e (patch)
tree9c492fcac3f1db65c2d308eabf0012c0b2f3b696 /Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration
parentb318f335991167102a5fa8d65030d200bbec898d (diff)
Prepared Seperation of Database components for future multi provider support
Diffstat (limited to 'Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration')
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ActivityLogConfiguration.cs17
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AncestorIdConfiguration.cs21
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ApiKeyConfiguration.cs20
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AttachmentStreamInfoConfiguration.cs17
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs57
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemMetadataFieldConfiguration.cs18
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs20
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemTrailerTypeConfiguration.cs18
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ChapterConfiguration.cs19
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/CustomItemDisplayPreferencesConfiguration.cs20
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceConfiguration.cs28
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceOptionsConfiguration.cs20
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DisplayPreferencesConfiguration.cs25
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesConfiguration.cs19
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesMapConfiguration.cs20
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/MediaStreamInfoConfiguration.cs22
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs22
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleConfiguration.cs20
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PermissionConfiguration.cs24
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PreferenceConfiguration.cs21
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/TrickplayInfoConfiguration.cs18
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserConfiguration.cs56
-rw-r--r--Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserDataConfiguration.cs23
23 files changed, 545 insertions, 0 deletions
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ActivityLogConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ActivityLogConfiguration.cs
new file mode 100644
index 000000000..9a63ed9f2
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ActivityLogConfiguration.cs
@@ -0,0 +1,17 @@
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// FluentAPI configuration for the ActivityLog entity.
+/// </summary>
+public class ActivityLogConfiguration : IEntityTypeConfiguration<ActivityLog>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<ActivityLog> builder)
+ {
+ builder.HasIndex(entity => entity.DateCreated);
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AncestorIdConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AncestorIdConfiguration.cs
new file mode 100644
index 000000000..8cc817fb8
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AncestorIdConfiguration.cs
@@ -0,0 +1,21 @@
+using System;
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// AncestorId configuration.
+/// </summary>
+public class AncestorIdConfiguration : IEntityTypeConfiguration<AncestorId>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<AncestorId> builder)
+ {
+ builder.HasKey(e => new { e.ItemId, e.ParentItemId });
+ builder.HasIndex(e => e.ParentItemId);
+ builder.HasOne(e => e.ParentItem).WithMany(e => e.ParentAncestors).HasForeignKey(f => f.ParentItemId);
+ builder.HasOne(e => e.Item).WithMany(e => e.Children).HasForeignKey(f => f.ItemId);
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ApiKeyConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ApiKeyConfiguration.cs
new file mode 100644
index 000000000..3f19b6986
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ApiKeyConfiguration.cs
@@ -0,0 +1,20 @@
+using Jellyfin.Data.Entities.Security;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration
+{
+ /// <summary>
+ /// FluentAPI configuration for the ApiKey entity.
+ /// </summary>
+ public class ApiKeyConfiguration : IEntityTypeConfiguration<ApiKey>
+ {
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<ApiKey> builder)
+ {
+ builder
+ .HasIndex(entity => entity.AccessToken)
+ .IsUnique();
+ }
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AttachmentStreamInfoConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AttachmentStreamInfoConfiguration.cs
new file mode 100644
index 000000000..057b6689a
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AttachmentStreamInfoConfiguration.cs
@@ -0,0 +1,17 @@
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// FluentAPI configuration for the AttachmentStreamInfo entity.
+/// </summary>
+public class AttachmentStreamInfoConfiguration : IEntityTypeConfiguration<AttachmentStreamInfo>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<AttachmentStreamInfo> builder)
+ {
+ builder.HasKey(e => new { e.ItemId, e.Index });
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs
new file mode 100644
index 000000000..08f2a3356
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs
@@ -0,0 +1,57 @@
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// Configuration for BaseItem.
+/// </summary>
+public class BaseItemConfiguration : IEntityTypeConfiguration<BaseItemEntity>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<BaseItemEntity> builder)
+ {
+ builder.HasKey(e => e.Id);
+ // TODO: See rant in entity file.
+ // builder.HasOne(e => e.Parent).WithMany(e => e.DirectChildren).HasForeignKey(e => e.ParentId);
+ // builder.HasOne(e => e.TopParent).WithMany(e => e.AllChildren).HasForeignKey(e => e.TopParentId);
+ // builder.HasOne(e => e.Season).WithMany(e => e.SeasonEpisodes).HasForeignKey(e => e.SeasonId);
+ // builder.HasOne(e => e.Series).WithMany(e => e.SeriesEpisodes).HasForeignKey(e => e.SeriesId);
+ builder.HasMany(e => e.Peoples);
+ builder.HasMany(e => e.UserData);
+ builder.HasMany(e => e.ItemValues);
+ builder.HasMany(e => e.MediaStreams);
+ builder.HasMany(e => e.Chapters);
+ builder.HasMany(e => e.Provider);
+ builder.HasMany(e => e.ParentAncestors);
+ builder.HasMany(e => e.Children);
+ builder.HasMany(e => e.LockedFields);
+ builder.HasMany(e => e.TrailerTypes);
+ builder.HasMany(e => e.Images);
+
+ builder.HasIndex(e => e.Path);
+ builder.HasIndex(e => e.ParentId);
+ builder.HasIndex(e => e.PresentationUniqueKey);
+ builder.HasIndex(e => new { e.Id, e.Type, e.IsFolder, e.IsVirtualItem });
+
+ // covering index
+ builder.HasIndex(e => new { e.TopParentId, e.Id });
+ // series
+ builder.HasIndex(e => new { e.Type, e.SeriesPresentationUniqueKey, e.PresentationUniqueKey, e.SortName });
+ // series counts
+ // seriesdateplayed sort order
+ builder.HasIndex(e => new { e.Type, e.SeriesPresentationUniqueKey, e.IsFolder, e.IsVirtualItem });
+ // live tv programs
+ builder.HasIndex(e => new { e.Type, e.TopParentId, e.StartDate });
+ // covering index for getitemvalues
+ builder.HasIndex(e => new { e.Type, e.TopParentId, e.Id });
+ // used by movie suggestions
+ builder.HasIndex(e => new { e.Type, e.TopParentId, e.PresentationUniqueKey });
+ // latest items
+ builder.HasIndex(e => new { e.Type, e.TopParentId, e.IsVirtualItem, e.PresentationUniqueKey, e.DateCreated });
+ builder.HasIndex(e => new { e.IsFolder, e.TopParentId, e.IsVirtualItem, e.PresentationUniqueKey, e.DateCreated });
+ // resume
+ builder.HasIndex(e => new { e.MediaType, e.TopParentId, e.IsVirtualItem, e.PresentationUniqueKey });
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemMetadataFieldConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemMetadataFieldConfiguration.cs
new file mode 100644
index 000000000..b4c6511bf
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemMetadataFieldConfiguration.cs
@@ -0,0 +1,18 @@
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// Provides configuration for the BaseItemMetadataField entity.
+/// </summary>
+public class BaseItemMetadataFieldConfiguration : IEntityTypeConfiguration<BaseItemMetadataField>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<BaseItemMetadataField> builder)
+ {
+ builder.HasKey(e => new { e.Id, e.ItemId });
+ builder.HasOne(e => e.Item);
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs
new file mode 100644
index 000000000..d15049a1f
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs
@@ -0,0 +1,20 @@
+using System;
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// BaseItemProvider configuration.
+/// </summary>
+public class BaseItemProviderConfiguration : IEntityTypeConfiguration<BaseItemProvider>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<BaseItemProvider> builder)
+ {
+ builder.HasKey(e => new { e.ItemId, e.ProviderId });
+ builder.HasOne(e => e.Item);
+ builder.HasIndex(e => new { e.ProviderId, e.ProviderValue, e.ItemId });
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemTrailerTypeConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemTrailerTypeConfiguration.cs
new file mode 100644
index 000000000..e9564b854
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemTrailerTypeConfiguration.cs
@@ -0,0 +1,18 @@
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// Provides configuration for the BaseItemMetadataField entity.
+/// </summary>
+public class BaseItemTrailerTypeConfiguration : IEntityTypeConfiguration<BaseItemTrailerType>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<BaseItemTrailerType> builder)
+ {
+ builder.HasKey(e => new { e.Id, e.ItemId });
+ builder.HasOne(e => e.Item);
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ChapterConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ChapterConfiguration.cs
new file mode 100644
index 000000000..5a84f7750
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ChapterConfiguration.cs
@@ -0,0 +1,19 @@
+using System;
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// Chapter configuration.
+/// </summary>
+public class ChapterConfiguration : IEntityTypeConfiguration<Chapter>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<Chapter> builder)
+ {
+ builder.HasKey(e => new { e.ItemId, e.ChapterIndex });
+ builder.HasOne(e => e.Item);
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/CustomItemDisplayPreferencesConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/CustomItemDisplayPreferencesConfiguration.cs
new file mode 100644
index 000000000..779aec986
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/CustomItemDisplayPreferencesConfiguration.cs
@@ -0,0 +1,20 @@
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration
+{
+ /// <summary>
+ /// FluentAPI configuration for the CustomItemDisplayPreferences entity.
+ /// </summary>
+ public class CustomItemDisplayPreferencesConfiguration : IEntityTypeConfiguration<CustomItemDisplayPreferences>
+ {
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<CustomItemDisplayPreferences> builder)
+ {
+ builder
+ .HasIndex(entity => new { entity.UserId, entity.ItemId, entity.Client, entity.Key })
+ .IsUnique();
+ }
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceConfiguration.cs
new file mode 100644
index 000000000..a750b65c0
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceConfiguration.cs
@@ -0,0 +1,28 @@
+using Jellyfin.Data.Entities.Security;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration
+{
+ /// <summary>
+ /// FluentAPI configuration for the Device entity.
+ /// </summary>
+ public class DeviceConfiguration : IEntityTypeConfiguration<Device>
+ {
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<Device> builder)
+ {
+ builder
+ .HasIndex(entity => new { entity.DeviceId, entity.DateLastActivity });
+
+ builder
+ .HasIndex(entity => new { entity.AccessToken, entity.DateLastActivity });
+
+ builder
+ .HasIndex(entity => new { entity.UserId, entity.DeviceId });
+
+ builder
+ .HasIndex(entity => entity.DeviceId);
+ }
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceOptionsConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceOptionsConfiguration.cs
new file mode 100644
index 000000000..038afd752
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceOptionsConfiguration.cs
@@ -0,0 +1,20 @@
+using Jellyfin.Data.Entities.Security;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration
+{
+ /// <summary>
+ /// FluentAPI configuration for the DeviceOptions entity.
+ /// </summary>
+ public class DeviceOptionsConfiguration : IEntityTypeConfiguration<DeviceOptions>
+ {
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<DeviceOptions> builder)
+ {
+ builder
+ .HasIndex(entity => entity.DeviceId)
+ .IsUnique();
+ }
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DisplayPreferencesConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DisplayPreferencesConfiguration.cs
new file mode 100644
index 000000000..9b437861b
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DisplayPreferencesConfiguration.cs
@@ -0,0 +1,25 @@
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration
+{
+ /// <summary>
+ /// FluentAPI configuration for the DisplayPreferencesConfiguration entity.
+ /// </summary>
+ public class DisplayPreferencesConfiguration : IEntityTypeConfiguration<DisplayPreferences>
+ {
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<DisplayPreferences> builder)
+ {
+ builder
+ .HasMany(d => d.HomeSections)
+ .WithOne()
+ .OnDelete(DeleteBehavior.Cascade);
+
+ builder
+ .HasIndex(entity => new { entity.UserId, entity.ItemId, entity.Client })
+ .IsUnique();
+ }
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesConfiguration.cs
new file mode 100644
index 000000000..abeeb09c9
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesConfiguration.cs
@@ -0,0 +1,19 @@
+using System;
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// itemvalues Configuration.
+/// </summary>
+public class ItemValuesConfiguration : IEntityTypeConfiguration<ItemValue>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<ItemValue> builder)
+ {
+ builder.HasKey(e => e.ItemValueId);
+ builder.HasIndex(e => new { e.Type, e.CleanValue }).IsUnique();
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesMapConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesMapConfiguration.cs
new file mode 100644
index 000000000..9c22b114c
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesMapConfiguration.cs
@@ -0,0 +1,20 @@
+using System;
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// itemvalues Configuration.
+/// </summary>
+public class ItemValuesMapConfiguration : IEntityTypeConfiguration<ItemValueMap>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<ItemValueMap> builder)
+ {
+ builder.HasKey(e => new { e.ItemValueId, e.ItemId });
+ builder.HasOne(e => e.Item);
+ builder.HasOne(e => e.ItemValue);
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/MediaStreamInfoConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/MediaStreamInfoConfiguration.cs
new file mode 100644
index 000000000..7e572f9a3
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/MediaStreamInfoConfiguration.cs
@@ -0,0 +1,22 @@
+using System;
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// People configuration.
+/// </summary>
+public class MediaStreamInfoConfiguration : IEntityTypeConfiguration<MediaStreamInfo>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<MediaStreamInfo> builder)
+ {
+ builder.HasKey(e => new { e.ItemId, e.StreamIndex });
+ builder.HasIndex(e => e.StreamIndex);
+ builder.HasIndex(e => e.StreamType);
+ builder.HasIndex(e => new { e.StreamIndex, e.StreamType });
+ builder.HasIndex(e => new { e.StreamIndex, e.StreamType, e.Language });
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs
new file mode 100644
index 000000000..cdaee9161
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs
@@ -0,0 +1,22 @@
+using System;
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// People configuration.
+/// </summary>
+public class PeopleBaseItemMapConfiguration : IEntityTypeConfiguration<PeopleBaseItemMap>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<PeopleBaseItemMap> builder)
+ {
+ builder.HasKey(e => new { e.ItemId, e.PeopleId });
+ builder.HasIndex(e => new { e.ItemId, e.SortOrder });
+ builder.HasIndex(e => new { e.ItemId, e.ListOrder });
+ builder.HasOne(e => e.Item);
+ builder.HasOne(e => e.People);
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleConfiguration.cs
new file mode 100644
index 000000000..f3cccb13f
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleConfiguration.cs
@@ -0,0 +1,20 @@
+using System;
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// People configuration.
+/// </summary>
+public class PeopleConfiguration : IEntityTypeConfiguration<People>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<People> builder)
+ {
+ builder.HasKey(e => e.Id);
+ builder.HasIndex(e => e.Name);
+ builder.HasMany(e => e.BaseItems);
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PermissionConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PermissionConfiguration.cs
new file mode 100644
index 000000000..240e284c0
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PermissionConfiguration.cs
@@ -0,0 +1,24 @@
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration
+{
+ /// <summary>
+ /// FluentAPI configuration for the Permission entity.
+ /// </summary>
+ public class PermissionConfiguration : IEntityTypeConfiguration<Permission>
+ {
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<Permission> builder)
+ {
+ // Used to get a user's permissions or a specific permission for a user.
+ // Also prevents multiple values being created for a user.
+ // Filtered over non-null user ids for when other entities (groups, API keys) get permissions
+ builder
+ .HasIndex(p => new { p.UserId, p.Kind })
+ .HasFilter("[UserId] IS NOT NULL")
+ .IsUnique();
+ }
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PreferenceConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PreferenceConfiguration.cs
new file mode 100644
index 000000000..49c869c6a
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PreferenceConfiguration.cs
@@ -0,0 +1,21 @@
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration
+{
+ /// <summary>
+ /// FluentAPI configuration for the Permission entity.
+ /// </summary>
+ public class PreferenceConfiguration : IEntityTypeConfiguration<Preference>
+ {
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<Preference> builder)
+ {
+ builder
+ .HasIndex(p => new { p.UserId, p.Kind })
+ .HasFilter("[UserId] IS NOT NULL")
+ .IsUnique();
+ }
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/TrickplayInfoConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/TrickplayInfoConfiguration.cs
new file mode 100644
index 000000000..dc1c17e5e
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/TrickplayInfoConfiguration.cs
@@ -0,0 +1,18 @@
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration
+{
+ /// <summary>
+ /// FluentAPI configuration for the TrickplayInfo entity.
+ /// </summary>
+ public class TrickplayInfoConfiguration : IEntityTypeConfiguration<TrickplayInfo>
+ {
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<TrickplayInfo> builder)
+ {
+ builder.HasKey(info => new { info.ItemId, info.Width });
+ }
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserConfiguration.cs
new file mode 100644
index 000000000..a369cf656
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserConfiguration.cs
@@ -0,0 +1,56 @@
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration
+{
+ /// <summary>
+ /// FluentAPI configuration for the User entity.
+ /// </summary>
+ public class UserConfiguration : IEntityTypeConfiguration<User>
+ {
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<User> builder)
+ {
+ builder
+ .Property(user => user.Username)
+ .UseCollation("NOCASE");
+
+ builder
+ .HasOne(u => u.ProfileImage)
+ .WithOne()
+ .OnDelete(DeleteBehavior.Cascade);
+
+ builder
+ .HasMany(u => u.Permissions)
+ .WithOne()
+ .HasForeignKey(p => p.UserId)
+ .OnDelete(DeleteBehavior.Cascade);
+
+ builder
+ .HasMany(u => u.Preferences)
+ .WithOne()
+ .HasForeignKey(p => p.UserId)
+ .OnDelete(DeleteBehavior.Cascade);
+
+ builder
+ .HasMany(u => u.AccessSchedules)
+ .WithOne()
+ .OnDelete(DeleteBehavior.Cascade);
+
+ builder
+ .HasMany(u => u.DisplayPreferences)
+ .WithOne()
+ .OnDelete(DeleteBehavior.Cascade);
+
+ builder
+ .HasMany(u => u.ItemDisplayPreferences)
+ .WithOne()
+ .OnDelete(DeleteBehavior.Cascade);
+
+ builder
+ .HasIndex(entity => entity.Username)
+ .IsUnique();
+ }
+ }
+}
diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserDataConfiguration.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserDataConfiguration.cs
new file mode 100644
index 000000000..7bbb28d43
--- /dev/null
+++ b/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserDataConfiguration.cs
@@ -0,0 +1,23 @@
+using System;
+using Jellyfin.Data.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace Jellyfin.Server.Implementations.ModelConfiguration;
+
+/// <summary>
+/// FluentAPI configuration for the UserData entity.
+/// </summary>
+public class UserDataConfiguration : IEntityTypeConfiguration<UserData>
+{
+ /// <inheritdoc/>
+ public void Configure(EntityTypeBuilder<UserData> builder)
+ {
+ builder.HasKey(d => new { d.ItemId, d.UserId, d.CustomDataKey });
+ builder.HasIndex(d => new { d.ItemId, d.UserId, d.Played });
+ builder.HasIndex(d => new { d.ItemId, d.UserId, d.PlaybackPositionTicks });
+ builder.HasIndex(d => new { d.ItemId, d.UserId, d.IsFavorite });
+ builder.HasIndex(d => new { d.ItemId, d.UserId, d.LastPlayedDate });
+ builder.HasOne(e => e.Item);
+ }
+}