< Summary - Jellyfin

Information
Class: Jellyfin.Database.Implementations.JellyfinDbContext
Assembly: Jellyfin.Database.Implementations
File(s): /srv/git/jellyfin/src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDbContext.cs
Line coverage
81%
Covered lines: 54
Uncovered lines: 12
Coverable lines: 66
Total lines: 331
Line coverage: 81.8%
Branch coverage
100%
Covered branches: 2
Total branches: 2
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 1/23/2026 - 12:11:06 AM Line coverage: 83.3% (45/54) Branch coverage: 100% (2/2) Total lines: 3264/19/2026 - 12:14:27 AM Line coverage: 81.5% (53/65) Branch coverage: 100% (2/2) Total lines: 3265/4/2026 - 12:15:16 AM Line coverage: 81.8% (54/66) Branch coverage: 100% (2/2) Total lines: 331 1/23/2026 - 12:11:06 AM Line coverage: 83.3% (45/54) Branch coverage: 100% (2/2) Total lines: 3264/19/2026 - 12:14:27 AM Line coverage: 81.5% (53/65) Branch coverage: 100% (2/2) Total lines: 3265/4/2026 - 12:15:16 AM Line coverage: 81.8% (54/66) Branch coverage: 100% (2/2) Total lines: 331

Coverage delta

Coverage delta 2 -2

Metrics

File(s)

/srv/git/jellyfin/src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDbContext.cs

#LineLine coverage
 1using System;
 2using System.Data.Common;
 3using System.Linq;
 4using System.Threading;
 5using System.Threading.Tasks;
 6using Jellyfin.Database.Implementations.Entities;
 7using Jellyfin.Database.Implementations.Entities.Security;
 8using Jellyfin.Database.Implementations.Interfaces;
 9using Jellyfin.Database.Implementations.Locking;
 10using Microsoft.EntityFrameworkCore;
 11using Microsoft.EntityFrameworkCore.Diagnostics;
 12using Microsoft.Extensions.Logging;
 13
 14namespace Jellyfin.Database.Implementations;
 15
 16/// <inheritdoc/>
 17/// <summary>
 18/// Initializes a new instance of the <see cref="JellyfinDbContext"/> class.
 19/// </summary>
 20/// <param name="options">The database context options.</param>
 21/// <param name="logger">Logger.</param>
 22/// <param name="jellyfinDatabaseProvider">The provider for the database engine specific operations.</param>
 23/// <param name="entityFrameworkCoreLocking">The locking behavior.</param>
 6424public class JellyfinDbContext(DbContextOptions<JellyfinDbContext> options, ILogger<JellyfinDbContext> logger, IJellyfin
 25{
 26    /// <summary>
 27    /// Gets the <see cref="DbSet{TEntity}"/> containing the access schedules.
 28    /// </summary>
 029    public DbSet<AccessSchedule> AccessSchedules => Set<AccessSchedule>();
 30
 31    /// <summary>
 32    /// Gets the <see cref="DbSet{TEntity}"/> containing the activity logs.
 33    /// </summary>
 3534    public DbSet<ActivityLog> ActivityLogs => Set<ActivityLog>();
 35
 36    /// <summary>
 37    /// Gets the <see cref="DbSet{TEntity}"/> containing the API keys.
 38    /// </summary>
 039    public DbSet<ApiKey> ApiKeys => Set<ApiKey>();
 40
 41    /// <summary>
 42    /// Gets the <see cref="DbSet{TEntity}"/> containing the devices.
 43    /// </summary>
 3644    public DbSet<Device> Devices => Set<Device>();
 45
 46    /// <summary>
 47    /// Gets the <see cref="DbSet{TEntity}"/> containing the device options.
 48    /// </summary>
 2149    public DbSet<DeviceOptions> DeviceOptions => Set<DeviceOptions>();
 50
 51    /// <summary>
 52    /// Gets the <see cref="DbSet{TEntity}"/> containing the display preferences.
 53    /// </summary>
 054    public DbSet<DisplayPreferences> DisplayPreferences => Set<DisplayPreferences>();
 55
 56    /// <summary>
 57    /// Gets the <see cref="DbSet{TEntity}"/> containing the image infos.
 58    /// </summary>
 059    public DbSet<ImageInfo> ImageInfos => Set<ImageInfo>();
 60
 61    /// <summary>
 62    /// Gets the <see cref="DbSet{TEntity}"/> containing the item display preferences.
 63    /// </summary>
 164    public DbSet<ItemDisplayPreferences> ItemDisplayPreferences => Set<ItemDisplayPreferences>();
 65
 66    /// <summary>
 67    /// Gets the <see cref="DbSet{TEntity}"/> containing the custom item display preferences.
 68    /// </summary>
 169    public DbSet<CustomItemDisplayPreferences> CustomItemDisplayPreferences => Set<CustomItemDisplayPreferences>();
 70
 71    /// <summary>
 72    /// Gets the <see cref="DbSet{TEntity}"/> containing the permissions.
 73    /// </summary>
 074    public DbSet<Permission> Permissions => Set<Permission>();
 75
 76    /// <summary>
 77    /// Gets the <see cref="DbSet{TEntity}"/> containing the preferences.
 78    /// </summary>
 079    public DbSet<Preference> Preferences => Set<Preference>();
 80
 81    /// <summary>
 82    /// Gets the <see cref="DbSet{TEntity}"/> containing the users.
 83    /// </summary>
 7684    public DbSet<User> Users => Set<User>();
 85
 86    /// <summary>
 87    /// Gets the <see cref="DbSet{TEntity}"/> containing the trickplay metadata.
 88    /// </summary>
 2289    public DbSet<TrickplayInfo> TrickplayInfos => Set<TrickplayInfo>();
 90
 91    /// <summary>
 92    /// Gets the <see cref="DbSet{TEntity}"/> containing the media segments.
 93    /// </summary>
 194    public DbSet<MediaSegment> MediaSegments => Set<MediaSegment>();
 95
 96    /// <summary>
 97    /// Gets the <see cref="DbSet{TEntity}"/> containing the user data.
 98    /// </summary>
 7099    public DbSet<UserData> UserData => Set<UserData>();
 100
 101    /// <summary>
 102    /// Gets the <see cref="DbSet{TEntity}"/> containing the user data.
 103    /// </summary>
 248104    public DbSet<AncestorId> AncestorIds => Set<AncestorId>();
 105
 106    /// <summary>
 107    /// Gets the <see cref="DbSet{TEntity}"/> containing the user data.
 108    /// </summary>
 1109    public DbSet<AttachmentStreamInfo> AttachmentStreamInfos => Set<AttachmentStreamInfo>();
 110
 111    /// <summary>
 112    /// Gets the <see cref="DbSet{TEntity}"/> containing the user data.
 113    /// </summary>
 847114    public DbSet<BaseItemEntity> BaseItems => Set<BaseItemEntity>();
 115
 116    /// <summary>
 117    /// Gets the <see cref="DbSet{TEntity}"/> containing the user data.
 118    /// </summary>
 7119    public DbSet<Chapter> Chapters => Set<Chapter>();
 120
 121    /// <summary>
 122    /// Gets the <see cref="DbSet{TEntity}"/>.
 123    /// </summary>
 286124    public DbSet<ItemValue> ItemValues => Set<ItemValue>();
 125
 126    /// <summary>
 127    /// Gets the <see cref="DbSet{TEntity}"/>.
 128    /// </summary>
 301129    public DbSet<ItemValueMap> ItemValuesMap => Set<ItemValueMap>();
 130
 131    /// <summary>
 132    /// Gets the <see cref="DbSet{TEntity}"/>.
 133    /// </summary>
 1134    public DbSet<MediaStreamInfo> MediaStreamInfos => Set<MediaStreamInfo>();
 135
 136    /// <summary>
 137    /// Gets the <see cref="DbSet{TEntity}"/>.
 138    /// </summary>
 1139    public DbSet<People> Peoples => Set<People>();
 140
 141    /// <summary>
 142    /// Gets the <see cref="DbSet{TEntity}"/>.
 143    /// </summary>
 2144    public DbSet<PeopleBaseItemMap> PeopleBaseItemMap => Set<PeopleBaseItemMap>();
 145
 146    /// <summary>
 147    /// Gets the <see cref="DbSet{TEntity}"/> containing linked children relationships.
 148    /// </summary>
 161149    public DbSet<LinkedChildEntity> LinkedChildren => Set<LinkedChildEntity>();
 150
 151    /// <summary>
 152    /// Gets the <see cref="DbSet{TEntity}"/> containing the referenced Providers with ids.
 153    /// </summary>
 53154    public DbSet<BaseItemProvider> BaseItemProviders => Set<BaseItemProvider>();
 155
 156    /// <summary>
 157    /// Gets the <see cref="DbSet{TEntity}"/>.
 158    /// </summary>
 53159    public DbSet<BaseItemImageInfo> BaseItemImageInfos => Set<BaseItemImageInfo>();
 160
 161    /// <summary>
 162    /// Gets the <see cref="DbSet{TEntity}"/>.
 163    /// </summary>
 53164    public DbSet<BaseItemMetadataField> BaseItemMetadataFields => Set<BaseItemMetadataField>();
 165
 166    /// <summary>
 167    /// Gets the <see cref="DbSet{TEntity}"/>.
 168    /// </summary>
 1169    public DbSet<BaseItemTrailerType> BaseItemTrailerTypes => Set<BaseItemTrailerType>();
 170
 171    /// <summary>
 172    /// Gets the <see cref="DbSet{TEntity}"/>.
 173    /// </summary>
 1174    public DbSet<KeyframeData> KeyframeData => Set<KeyframeData>();
 175
 176    /*public DbSet<Artwork> Artwork => Set<Artwork>();
 177
 178    public DbSet<Book> Books => Set<Book>();
 179
 180    public DbSet<BookMetadata> BookMetadata => Set<BookMetadata>();
 181
 182    public DbSet<Chapter> Chapters => Set<Chapter>();
 183
 184    public DbSet<Collection> Collections => Set<Collection>();
 185
 186    public DbSet<CollectionItem> CollectionItems => Set<CollectionItem>();
 187
 188    public DbSet<Company> Companies => Set<Company>();
 189
 190    public DbSet<CompanyMetadata> CompanyMetadata => Set<CompanyMetadata>();
 191
 192    public DbSet<CustomItem> CustomItems => Set<CustomItem>();
 193
 194    public DbSet<CustomItemMetadata> CustomItemMetadata => Set<CustomItemMetadata>();
 195
 196    public DbSet<Episode> Episodes => Set<Episode>();
 197
 198    public DbSet<EpisodeMetadata> EpisodeMetadata => Set<EpisodeMetadata>();
 199
 200    public DbSet<Genre> Genres => Set<Genre>();
 201
 202    public DbSet<Group> Groups => Set<Groups>();
 203
 204    public DbSet<Library> Libraries => Set<Library>();
 205
 206    public DbSet<LibraryItem> LibraryItems => Set<LibraryItems>();
 207
 208    public DbSet<LibraryRoot> LibraryRoot => Set<LibraryRoot>();
 209
 210    public DbSet<MediaFile> MediaFiles => Set<MediaFiles>();
 211
 212    public DbSet<MediaFileStream> MediaFileStream => Set<MediaFileStream>();
 213
 214    public DbSet<Metadata> Metadata => Set<Metadata>();
 215
 216    public DbSet<MetadataProvider> MetadataProviders => Set<MetadataProvider>();
 217
 218    public DbSet<MetadataProviderId> MetadataProviderIds => Set<MetadataProviderId>();
 219
 220    public DbSet<Movie> Movies => Set<Movie>();
 221
 222    public DbSet<MovieMetadata> MovieMetadata => Set<MovieMetadata>();
 223
 224    public DbSet<MusicAlbum> MusicAlbums => Set<MusicAlbum>();
 225
 226    public DbSet<MusicAlbumMetadata> MusicAlbumMetadata => Set<MusicAlbumMetadata>();
 227
 228    public DbSet<Person> People => Set<Person>();
 229
 230    public DbSet<PersonRole> PersonRoles => Set<PersonRole>();
 231
 232    public DbSet<Photo> Photo => Set<Photo>();
 233
 234    public DbSet<PhotoMetadata> PhotoMetadata => Set<PhotoMetadata>();
 235
 236    public DbSet<ProviderMapping> ProviderMappings => Set<ProviderMapping>();
 237
 238    public DbSet<Rating> Ratings => Set<Rating>();
 239
 240    /// <summary>
 241    /// Repository for global::Jellyfin.Data.Entities.RatingSource - This is the entity to
 242    /// store review ratings, not age ratings.
 243    /// </summary>
 244    public DbSet<RatingSource> RatingSources => Set<RatingSource>();
 245
 246    public DbSet<Release> Releases => Set<Release>();
 247
 248    public DbSet<Season> Seasons => Set<Season>();
 249
 250    public DbSet<SeasonMetadata> SeasonMetadata => Set<SeasonMetadata>();
 251
 252    public DbSet<Series> Series => Set<Series>();
 253
 254    public DbSet<SeriesMetadata> SeriesMetadata => Set<SeriesMetadata();
 255
 256    public DbSet<Track> Tracks => Set<Track>();
 257
 258    public DbSet<TrackMetadata> TrackMetadata => Set<TrackMetadata>();*/
 259
 260    /// <inheritdoc/>
 261    public override async Task<int> SaveChangesAsync(
 262        bool acceptAllChangesOnSuccess,
 263        CancellationToken cancellationToken = default)
 264    {
 85265        HandleConcurrencyToken();
 266
 267        try
 268        {
 85269            var result = -1;
 85270            await entityFrameworkCoreLocking.OnSaveChangesAsync(this, async () =>
 85271            {
 85272                result = await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken).ConfigureAwait(false)
 85273            }).ConfigureAwait(false);
 85274            return result;
 275        }
 0276        catch (Exception e)
 277        {
 0278            logger.LogError(e, "Error trying to save changes.");
 0279            throw;
 280        }
 85281    }
 282
 283    /// <inheritdoc/>
 284    public override int SaveChanges(bool acceptAllChangesOnSuccess) // SaveChanges(bool) is beeing called by SaveChanges
 285    {
 237286        HandleConcurrencyToken();
 287
 288        try
 289        {
 237290            var result = -1;
 237291            entityFrameworkCoreLocking.OnSaveChanges(this, () =>
 237292            {
 237293                result = base.SaveChanges(acceptAllChangesOnSuccess);
 237294            });
 237295            return result;
 296        }
 0297        catch (Exception e)
 298        {
 0299            logger.LogError(e, "Error trying to save changes.");
 0300            throw;
 301        }
 237302    }
 303
 304    private void HandleConcurrencyToken()
 305    {
 682306        foreach (var saveEntity in ChangeTracker.Entries()
 322307                     .Where(e => e.State == EntityState.Modified)
 322308                     .Select(entry => entry.Entity)
 322309                     .OfType<IHasConcurrencyToken>())
 310        {
 19311            saveEntity.OnSavingChanges();
 312        }
 322313    }
 314
 315    /// <inheritdoc />
 316    protected override void OnModelCreating(ModelBuilder modelBuilder)
 317    {
 2318        jellyfinDatabaseProvider.OnModelCreating(modelBuilder);
 2319        base.OnModelCreating(modelBuilder);
 320
 321        // Configuration for each entity is in its own class inside 'ModelConfiguration'.
 2322        modelBuilder.ApplyConfigurationsFromAssembly(typeof(JellyfinDbContext).Assembly);
 2323    }
 324
 325    /// <inheritdoc />
 326    protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
 327    {
 2328        jellyfinDatabaseProvider.ConfigureConventions(configurationBuilder);
 2329        base.ConfigureConventions(configurationBuilder);
 2330    }
 331}