diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutAllHandler.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutAllHandler.cs index 54a8d556..31d37c19 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutAllHandler.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutAllHandler.cs @@ -46,7 +46,6 @@ public class YamlPlayoutAllHandler(EnumeratorCache enumeratorCache) : YamlPlayou // create a playout item var playoutItem = new PlayoutItem { - MediaItem = mediaItem, MediaItemId = mediaItem.Id, Start = context.CurrentTime.UtcDateTime, Finish = context.CurrentTime.UtcDateTime + itemDuration, @@ -72,7 +71,7 @@ public class YamlPlayoutAllHandler(EnumeratorCache enumeratorCache) : YamlPlayou playoutItem.WatermarkId = watermarkId; } - await AddItemAndMidRoll(context, playoutItem, executeSequence); + await AddItemAndMidRoll(context, playoutItem, mediaItem, executeSequence); context.AdvanceGuideGroup(); // create history record diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutContentHandler.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutContentHandler.cs index 17903234..ee2d94d4 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutContentHandler.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutContentHandler.cs @@ -170,10 +170,13 @@ public abstract class YamlPlayoutContentHandler(EnumeratorCache enumeratorCache) return Optional(version.Chapters).Flatten().OrderBy(c => c.StartTime).ToList(); } - protected static async Task AddItemAndMidRoll(YamlPlayoutContext context, PlayoutItem playoutItem, + protected static async Task AddItemAndMidRoll( + YamlPlayoutContext context, + PlayoutItem playoutItem, + MediaItem mediaItem, Func executeSequence) { - List itemChapters = ChaptersForMediaItem(playoutItem.MediaItem); + List itemChapters = ChaptersForMediaItem(mediaItem); Option maybeMidRollSequence = context.GetMidRollSequence(); if (itemChapters.Count < 2 || maybeMidRollSequence.IsNone) { diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutCountHandler.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutCountHandler.cs index 39813480..f0755d31 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutCountHandler.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutCountHandler.cs @@ -71,7 +71,6 @@ public class YamlPlayoutCountHandler(EnumeratorCache enumeratorCache) : YamlPlay // create a playout item var playoutItem = new PlayoutItem { - MediaItem = mediaItem, MediaItemId = mediaItem.Id, Start = context.CurrentTime.UtcDateTime, Finish = context.CurrentTime.UtcDateTime + itemDuration, @@ -97,7 +96,7 @@ public class YamlPlayoutCountHandler(EnumeratorCache enumeratorCache) : YamlPlay playoutItem.WatermarkId = watermarkId; } - await AddItemAndMidRoll(context, playoutItem, executeSequence); + await AddItemAndMidRoll(context, playoutItem, mediaItem, executeSequence); context.AdvanceGuideGroup(); // create history record diff --git a/ErsatzTV.Infrastructure/Data/Repositories/ChannelRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/ChannelRepository.cs index 2c4401ab..5b71cc9a 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/ChannelRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/ChannelRepository.cs @@ -15,6 +15,7 @@ public class ChannelRepository : IChannelRepository { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); return await dbContext.Channels + .AsNoTracking() .Include(c => c.Artwork) .Include(c => c.Watermark) .OrderBy(c => c.Id) @@ -26,6 +27,7 @@ public class ChannelRepository : IChannelRepository { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); return await dbContext.Channels + .AsNoTracking() .Include(c => c.FFmpegProfile) .ThenInclude(p => p.Resolution) .Include(c => c.Artwork) @@ -39,6 +41,7 @@ public class ChannelRepository : IChannelRepository { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); return await dbContext.Channels + .AsNoTracking() .Include(c => c.FFmpegProfile) .Include(c => c.Artwork) .Include(c => c.Playouts) @@ -50,6 +53,7 @@ public class ChannelRepository : IChannelRepository await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); List maybeWatermarks = await dbContext.ChannelWatermarks + .AsNoTracking() .Where(cw => EF.Functions.Like( EF.Functions.Collate(cw.Name, TvContext.CaseInsensitiveCollation), $"%{name}%")) diff --git a/ErsatzTV.Infrastructure/Data/Repositories/ConfigElementRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/ConfigElementRepository.cs index ff2df5fa..bcb3f604 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/ConfigElementRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/ConfigElementRepository.cs @@ -45,6 +45,7 @@ public class ConfigElementRepository : IConfigElementRepository { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); return await dbContext.ConfigElements + .AsNoTracking() .OrderBy(ce => ce.Key) .SingleOrDefaultAsync(ce => ce.Key == key.Key) .Map(Optional); diff --git a/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs index f1939d9c..8da40c82 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs @@ -35,6 +35,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository var result = new Dictionary>(); Option maybePlaylist = await dbContext.Playlists + .AsNoTracking() .Include(p => p.Items) .SelectOneAsync(p => p.Id, p => p.Id == playlistId); @@ -169,6 +170,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); Option maybePlaylist = await dbContext.Playlists + .AsNoTracking() .SelectOneAsync(p => p.Name, p => EF.Functions.Collate(p.Name, TvContext.CaseInsensitiveCollation) == name); foreach (Playlist playlist in maybePlaylist) @@ -315,6 +317,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); return await dbContext.Collections + .AsNoTracking() .Include(c => c.CollectionItems) .OrderBy(c => c.Id) .SingleOrDefaultAsync(c => c.Id == id) @@ -346,6 +349,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); Option maybeCollection = await dbContext.Collections + .AsNoTracking() .SelectOneAsync(c => c.Name, c => EF.Functions.Collate(c.Name, TvContext.CaseInsensitiveCollation) == name); foreach (Collection collection in maybeCollection) @@ -363,6 +367,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository var result = new List(); Option maybeMultiCollection = await dbContext.MultiCollections + .AsNoTracking() .Include(mc => mc.Collections) .Include(mc => mc.SmartCollections) .SelectOneAsync(mc => mc.Id, mc => mc.Id == id); @@ -397,6 +402,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); Option maybeCollection = await dbContext.MultiCollections + .AsNoTracking() .SelectOneAsync( mc => mc.Name, mc => EF.Functions.Collate(mc.Name, TvContext.CaseInsensitiveCollation) == name); @@ -414,6 +420,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); Option maybeCollection = await dbContext.SmartCollections + .AsNoTracking() .SelectOneAsync(sc => sc.Id, sc => sc.Id == id); foreach (SmartCollection collection in maybeCollection) @@ -429,6 +436,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(); Option maybeCollection = await dbContext.SmartCollections + .AsNoTracking() .SelectOneAsync( sc => sc.Name, sc => EF.Functions.Collate(sc.Name, TvContext.CaseInsensitiveCollation) == name); @@ -529,6 +537,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository } List nextIds = await dbContext.ShowMetadata + .AsNoTracking() .Filter(sm => sm.Guids.Any(g => EF.Functions.Collate(g.Guid, TvContext.CaseInsensitiveCollation) == guid)) .Map(sm => sm.ShowId) @@ -556,6 +565,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository var result = new List(); Option maybeMultiCollection = await dbContext.MultiCollections + .AsNoTracking() .Include(mc => mc.Collections) .Include(mc => mc.SmartCollections) .Include(mc => mc.MultiCollectionItems) @@ -643,6 +653,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository var result = new List(); Option maybePlaylist = await dbContext.Playlists + .AsNoTracking() .Include(p => p.Items) .SelectOneAsync(p => p.Id, p => p.Id == id); @@ -876,25 +887,32 @@ public class MediaCollectionRepository : IMediaCollectionRepository return emptyCollection.CollectionType switch { - ProgramScheduleItemCollectionType.Artist => await dbContext.Artists.Include(a => a.ArtistMetadata) + ProgramScheduleItemCollectionType.Artist => await dbContext.Artists + .AsNoTracking() + .Include(a => a.ArtistMetadata) .SelectOneAsync(a => a.Id, a => a.Id == emptyCollection.MediaItemId.Value) .MapT(a => a.ArtistMetadata.Head().Title), ProgramScheduleItemCollectionType.Collection => await dbContext.Collections + .AsNoTracking() .SelectOneAsync(c => c.Id, c => c.Id == emptyCollection.CollectionId.Value) .MapT(c => c.Name), ProgramScheduleItemCollectionType.MultiCollection => await dbContext.MultiCollections + .AsNoTracking() .SelectOneAsync(c => c.Id, c => c.Id == emptyCollection.MultiCollectionId.Value) .MapT(c => c.Name), ProgramScheduleItemCollectionType.SmartCollection => await dbContext.SmartCollections + .AsNoTracking() .SelectOneAsync(c => c.Id, c => c.Id == emptyCollection.SmartCollectionId.Value) .MapT(c => c.Name), ProgramScheduleItemCollectionType.TelevisionSeason => await dbContext.Seasons + .AsNoTracking() .Include(s => s.SeasonMetadata) .Include(s => s.Show) .ThenInclude(s => s.ShowMetadata) .SelectOneAsync(a => a.Id, a => a.Id == emptyCollection.MediaItemId.Value) .MapT(s => $"{s.Show.ShowMetadata.Head().Title} Season {s.SeasonNumber}"), ProgramScheduleItemCollectionType.TelevisionShow => await dbContext.Shows.Include(s => s.ShowMetadata) + .AsNoTracking() .SelectOneAsync(a => a.Id, a => a.Id == emptyCollection.MediaItemId.Value) .MapT(s => s.ShowMetadata.Head().Title), // TODO: get playlist name @@ -1049,6 +1067,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository private static Task> GetMovieItems(TvContext dbContext, IEnumerable movieIds) => dbContext.Movies + .AsNoTracking() .Include(m => m.MovieMetadata) .ThenInclude(mm => mm.Subtitles) .Include(m => m.MediaVersions) @@ -1074,6 +1093,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository TvContext dbContext, IEnumerable musicVideoIds) => dbContext.MusicVideos + .AsNoTracking() .Include(m => m.Artist) .ThenInclude(a => a.ArtistMetadata) .Include(m => m.MusicVideoMetadata) @@ -1109,6 +1129,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository private static Task> GetMusicVideoItems(TvContext dbContext, IEnumerable musicVideoIds) => dbContext.MusicVideos + .AsNoTracking() .Include(m => m.Artist) .ThenInclude(a => a.ArtistMetadata) .Include(m => m.MusicVideoMetadata) @@ -1135,6 +1156,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository private static Task> GetOtherVideoItems(TvContext dbContext, IEnumerable otherVideoIds) => dbContext.OtherVideos + .AsNoTracking() .Include(m => m.OtherVideoMetadata) .ThenInclude(ovm => ovm.Subtitles) .Include(m => m.MediaVersions) @@ -1157,6 +1179,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository private static Task> GetSongItems(TvContext dbContext, IEnumerable songIds) => dbContext.Songs + .AsNoTracking() .Include(m => m.SongMetadata) .ThenInclude(s => s.Subtitles) .Include(m => m.MediaVersions) @@ -1179,6 +1202,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository private static Task> GetImageItems(TvContext dbContext, IEnumerable imageIds) => dbContext.Images + .AsNoTracking() .Include(m => m.ImageMetadata) .ThenInclude(im => im.Subtitles) .Include(m => m.MediaVersions) @@ -1201,6 +1225,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository private static Task> GetRemoteStreamItems(TvContext dbContext, IEnumerable remoteStreamIds) => dbContext.RemoteStreams + .AsNoTracking() .Include(m => m.RemoteStreamMetadata) .ThenInclude(im => im.Subtitles) .Include(m => m.MediaVersions) @@ -1227,6 +1252,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository private static Task> GetShowItemsFromEpisodeIds(TvContext dbContext, IEnumerable episodeIds) => dbContext.Episodes + .AsNoTracking() .Include(e => e.EpisodeMetadata) .ThenInclude(em => em.Subtitles) .Include(e => e.MediaVersions) @@ -1265,6 +1291,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository private static Task> GetSeasonItemsFromEpisodeIds(TvContext dbContext, IEnumerable episodeIds) => dbContext.Episodes + .AsNoTracking() .Include(e => e.EpisodeMetadata) .ThenInclude(em => em.Subtitles) .Include(e => e.MediaVersions) @@ -1301,6 +1328,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository private static Task> GetEpisodeItems(TvContext dbContext, IEnumerable episodeIds) => dbContext.Episodes + .AsNoTracking() .Include(e => e.EpisodeMetadata) .ThenInclude(em => em.Subtitles) .Include(e => e.MediaVersions)