Initial commit
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class ChannelConfiguration : IEntityTypeConfiguration<Channel>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Channel> builder)
|
||||
{
|
||||
builder.HasIndex(c => c.Number)
|
||||
.IsUnique();
|
||||
|
||||
builder.HasMany(c => c.Playouts) // TODO: is this correct, or should we have one to one?
|
||||
.WithOne(p => p.Channel)
|
||||
.HasForeignKey(p => p.ChannelId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class ConfigElementConfiguration : IEntityTypeConfiguration<ConfigElement>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ConfigElement> builder) =>
|
||||
builder.HasIndex(ce => ce.Key)
|
||||
.IsUnique();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.AggregateModels;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class GenericIntegerIdConfiguration : IEntityTypeConfiguration<GenericIntegerId>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<GenericIntegerId> builder) =>
|
||||
builder.HasNoKey();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class LocalMediaSourceConfiguration : IEntityTypeConfiguration<LocalMediaSource>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<LocalMediaSource> builder) =>
|
||||
builder.ToTable("LocalMediaSources");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class MediaCollectionConfiguration : IEntityTypeConfiguration<MediaCollection>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<MediaCollection> builder) =>
|
||||
builder.HasIndex(c => c.Name).IsUnique();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.AggregateModels;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class MediaCollectionSummaryConfiguration : IEntityTypeConfiguration<MediaCollectionSummary>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<MediaCollectionSummary> builder) =>
|
||||
builder.HasNoKey();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class MediaItemConfiguration : IEntityTypeConfiguration<MediaItem>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<MediaItem> builder) =>
|
||||
builder.OwnsOne(c => c.Metadata).WithOwner();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class MediaSourceConfiguration : IEntityTypeConfiguration<MediaSource>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<MediaSource> builder) =>
|
||||
builder.HasIndex(ms => ms.Name).IsUnique();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class PlayoutConfiguration : IEntityTypeConfiguration<Playout>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Playout> builder)
|
||||
{
|
||||
builder.HasMany(p => p.Items)
|
||||
.WithOne(pi => pi.Playout)
|
||||
.HasForeignKey(pi => pi.PlayoutId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.OwnsOne(c => c.Anchor);
|
||||
|
||||
builder.HasMany(p => p.ProgramScheduleAnchors)
|
||||
.WithOne(a => a.Playout)
|
||||
.HasForeignKey(a => a.PlayoutId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class PlayoutProgramScheduleAnchorConfiguration : IEntityTypeConfiguration<PlayoutProgramScheduleAnchor>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PlayoutProgramScheduleAnchor> builder)
|
||||
{
|
||||
builder.HasKey(a => new { a.PlayoutId, a.ProgramScheduleId, ContentGroupId = a.MediaCollectionId });
|
||||
|
||||
builder.OwnsOne(a => a.EnumeratorState);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class PlexMediaSourceConfiguration : IEntityTypeConfiguration<PlexMediaSource>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PlexMediaSource> builder) => builder.ToTable("PlexMediaSources");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class PlexMediaSourceConnectionConfiguration : IEntityTypeConfiguration<PlexMediaSourceConnection>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PlexMediaSourceConnection> builder) =>
|
||||
builder.ToTable("PlexMediaSourceConnections");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class PlexMediaSourceLibraryConfiguration : IEntityTypeConfiguration<PlexMediaSourceLibrary>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PlexMediaSourceLibrary> builder) =>
|
||||
builder.ToTable("PlexMediaSourceLibraries");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class ProgramScheduleConfiguration : IEntityTypeConfiguration<ProgramSchedule>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ProgramSchedule> builder)
|
||||
{
|
||||
builder.HasIndex(ps => ps.Name)
|
||||
.IsUnique();
|
||||
|
||||
builder.HasMany(ps => ps.Items)
|
||||
.WithOne(i => i.ProgramSchedule)
|
||||
.HasForeignKey(i => i.ProgramScheduleId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasMany(ps => ps.Playouts)
|
||||
.WithOne(p => p.ProgramSchedule)
|
||||
.HasForeignKey(p => p.ProgramScheduleId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class ProgramScheduleItemConfiguration : IEntityTypeConfiguration<ProgramScheduleItem>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ProgramScheduleItem> builder) =>
|
||||
builder.ToTable("ProgramScheduleItems");
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class ProgramScheduleItemDurationConfiguration : IEntityTypeConfiguration<ProgramScheduleItemDuration>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ProgramScheduleItemDuration> builder) =>
|
||||
builder.ToTable("ProgramScheduleDurationItems");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class ProgramScheduleItemFloodConfiguration : IEntityTypeConfiguration<ProgramScheduleItemFlood>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ProgramScheduleItemFlood> builder) =>
|
||||
builder.ToTable("ProgramScheduleFloodItems");
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class ProgramScheduleItemMultipleConfiguration : IEntityTypeConfiguration<ProgramScheduleItemMultiple>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ProgramScheduleItemMultiple> builder) =>
|
||||
builder.ToTable("ProgramScheduleMultipleItems");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class ProgramScheduleItemOneConfiguration : IEntityTypeConfiguration<ProgramScheduleItemOne>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ProgramScheduleItemOne> builder) =>
|
||||
builder.ToTable("ProgramScheduleOneItems");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class SimpleMediaCollectionConfiguration : IEntityTypeConfiguration<SimpleMediaCollection>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<SimpleMediaCollection> builder)
|
||||
{
|
||||
builder.ToTable("SimpleMediaCollections");
|
||||
|
||||
builder.HasMany(cg => cg.Items)
|
||||
.WithMany(c => c.SimpleMediaCollections);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class TelevisionMediaCollectionConfiguration : IEntityTypeConfiguration<TelevisionMediaCollection>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<TelevisionMediaCollection> builder)
|
||||
{
|
||||
builder.ToTable("TelevisionMediaCollections");
|
||||
|
||||
builder.HasIndex(c => new { c.ShowTitle, c.SeasonNumber })
|
||||
.IsUnique();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using LanguageExt;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data
|
||||
{
|
||||
public static class DbInitializer
|
||||
{
|
||||
public static Unit Initialize(TvContext context)
|
||||
{
|
||||
if (context.Resolutions.Any())
|
||||
{
|
||||
return Unit.Default;
|
||||
}
|
||||
|
||||
var resolutions = new List<Resolution>
|
||||
{
|
||||
new() { Id = 1, Name = "720x480", Width = 720, Height = 480 },
|
||||
new() { Id = 2, Name = "1280x720", Width = 1280, Height = 720 },
|
||||
new() { Id = 3, Name = "1920x1080", Width = 1920, Height = 1080 },
|
||||
new() { Id = 4, Name = "3840x2160", Width = 3840, Height = 2160 }
|
||||
};
|
||||
context.Resolutions.AddRange(resolutions);
|
||||
context.SaveChanges();
|
||||
|
||||
var resolutionConfig = new ConfigElement
|
||||
{
|
||||
Key = ConfigElementKey.FFmpegDefaultResolutionId.Key,
|
||||
Value = "3" // 1920x1080
|
||||
};
|
||||
context.ConfigElements.Add(resolutionConfig);
|
||||
context.SaveChanges();
|
||||
|
||||
var defaultProfile = FFmpegProfile.New("1920x1080 x264 ac3", resolutions[2]);
|
||||
context.FFmpegProfiles.Add(defaultProfile);
|
||||
context.SaveChanges();
|
||||
|
||||
var profileConfig = new ConfigElement
|
||||
{
|
||||
Key = ConfigElementKey.FFmpegDefaultProfileId.Key,
|
||||
Value = defaultProfile.Id.ToString()
|
||||
};
|
||||
context.ConfigElements.Add(profileConfig);
|
||||
context.SaveChanges();
|
||||
|
||||
var defaultChannel = new Channel(Guid.NewGuid())
|
||||
{
|
||||
Number = 1,
|
||||
Name = "ErsatzTV",
|
||||
FFmpegProfile = defaultProfile,
|
||||
StreamingMode = StreamingMode.TransportStream
|
||||
};
|
||||
context.Channels.Add(defaultChannel);
|
||||
context.SaveChanges();
|
||||
|
||||
// TODO: clean this up
|
||||
// var mediaSource = new LocalMediaSource
|
||||
// {
|
||||
// Name = "Default"
|
||||
// };
|
||||
// context.MediaSources.Add(mediaSource);
|
||||
// context.SaveChanges();
|
||||
|
||||
// TODO: create looping static image that mentions configuring via web
|
||||
return Unit.Default;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using LanguageExt;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using static LanguageExt.Prelude;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
{
|
||||
public class ChannelRepository : IChannelRepository
|
||||
{
|
||||
private readonly TvContext _dbContext;
|
||||
|
||||
public ChannelRepository(TvContext dbContext) => _dbContext = dbContext;
|
||||
|
||||
public async Task<Channel> Add(Channel channel)
|
||||
{
|
||||
await _dbContext.Channels.AddAsync(channel);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return channel;
|
||||
}
|
||||
|
||||
public Task<Option<Channel>> Get(int id) =>
|
||||
_dbContext.Channels.SingleOrDefaultAsync(c => c.Id == id).Map(Optional);
|
||||
|
||||
public Task<Option<Channel>> GetByNumber(int number) =>
|
||||
_dbContext.Channels
|
||||
.Include(c => c.FFmpegProfile)
|
||||
.ThenInclude(p => p.Resolution)
|
||||
.SingleOrDefaultAsync(c => c.Number == number)
|
||||
.Map(Optional);
|
||||
|
||||
public Task<List<Channel>> GetAll() => _dbContext.Channels.ToListAsync();
|
||||
|
||||
public Task<List<Channel>> GetAllForGuide() =>
|
||||
_dbContext.Channels
|
||||
.Include(c => c.Playouts)
|
||||
.ThenInclude(p => p.Items)
|
||||
.ThenInclude(i => i.MediaItem)
|
||||
.ToListAsync();
|
||||
|
||||
public async Task Update(Channel channel)
|
||||
{
|
||||
_dbContext.Channels.Update(channel);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task Delete(int channelId)
|
||||
{
|
||||
Channel channel = await _dbContext.Channels.FindAsync(channelId);
|
||||
_dbContext.Channels.Remove(channel);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using LanguageExt;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
{
|
||||
public class ConfigElementRepository : IConfigElementRepository
|
||||
{
|
||||
private readonly TvContext _dbContext;
|
||||
|
||||
public ConfigElementRepository(TvContext dbContext) => _dbContext = dbContext;
|
||||
|
||||
public async Task<ConfigElement> Add(ConfigElement configElement)
|
||||
{
|
||||
await _dbContext.ConfigElements.AddAsync(configElement);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return configElement;
|
||||
}
|
||||
|
||||
public async Task<Option<ConfigElement>> Get(ConfigElementKey key) =>
|
||||
await _dbContext.ConfigElements.SingleOrDefaultAsync(ce => ce.Key == key.Key);
|
||||
|
||||
public Task<Option<T>> GetValue<T>(ConfigElementKey key) =>
|
||||
Get(key).MapT(ce => (T) Convert.ChangeType(ce.Value, typeof(T)));
|
||||
|
||||
public async Task Update(ConfigElement configElement)
|
||||
{
|
||||
_dbContext.ConfigElements.Update(configElement);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task Delete(ConfigElement configElement)
|
||||
{
|
||||
_dbContext.ConfigElements.Remove(configElement);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using LanguageExt;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
{
|
||||
public class FFmpegProfileRepository : IFFmpegProfileRepository
|
||||
{
|
||||
private readonly TvContext _dbContext;
|
||||
|
||||
public FFmpegProfileRepository(TvContext dbContext) => _dbContext = dbContext;
|
||||
|
||||
public async Task<FFmpegProfile> Add(FFmpegProfile ffmpegProfile)
|
||||
{
|
||||
await _dbContext.FFmpegProfiles.AddAsync(ffmpegProfile);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return ffmpegProfile;
|
||||
}
|
||||
|
||||
public async Task<Option<FFmpegProfile>> Get(int id) =>
|
||||
await _dbContext.FFmpegProfiles
|
||||
.Include(p => p.Resolution)
|
||||
.SingleOrDefaultAsync(p => p.Id == id);
|
||||
|
||||
public Task<List<FFmpegProfile>> GetAll() =>
|
||||
_dbContext.FFmpegProfiles
|
||||
.Include(p => p.Resolution)
|
||||
.ToListAsync();
|
||||
|
||||
public async Task Update(FFmpegProfile ffmpegProfile)
|
||||
{
|
||||
_dbContext.FFmpegProfiles.Update(ffmpegProfile);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task Delete(int ffmpegProfileId)
|
||||
{
|
||||
FFmpegProfile ffmpegProfile = await _dbContext.FFmpegProfiles.FindAsync(ffmpegProfileId);
|
||||
_dbContext.FFmpegProfiles.Remove(ffmpegProfile);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ErsatzTV.Core.AggregateModels;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using LanguageExt;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using static LanguageExt.Prelude;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
{
|
||||
public class MediaCollectionRepository : IMediaCollectionRepository
|
||||
{
|
||||
private readonly TvContext _dbContext;
|
||||
|
||||
public MediaCollectionRepository(TvContext dbContext) => _dbContext = dbContext;
|
||||
|
||||
public async Task<SimpleMediaCollection> Add(SimpleMediaCollection collection)
|
||||
{
|
||||
await _dbContext.SimpleMediaCollections.AddAsync(collection);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return collection;
|
||||
}
|
||||
|
||||
public Task<Option<MediaCollection>> Get(int id) =>
|
||||
_dbContext.MediaCollections.SingleOrDefaultAsync(c => c.Id == id).Map(Optional);
|
||||
|
||||
public Task<Option<SimpleMediaCollection>> GetSimpleMediaCollection(int id) =>
|
||||
Get(id).Map(c => c.OfType<SimpleMediaCollection>().HeadOrNone());
|
||||
|
||||
public Task<Option<TelevisionMediaCollection>> GetTelevisionMediaCollection(int id) =>
|
||||
Get(id).Map(c => c.OfType<TelevisionMediaCollection>().HeadOrNone());
|
||||
|
||||
public Task<List<SimpleMediaCollection>> GetSimpleMediaCollections() =>
|
||||
_dbContext.SimpleMediaCollections.ToListAsync();
|
||||
|
||||
public Task<List<MediaCollection>> GetAll() =>
|
||||
_dbContext.MediaCollections.ToListAsync();
|
||||
|
||||
public Task<List<MediaCollectionSummary>> GetSummaries(string searchString) =>
|
||||
_dbContext.MediaCollectionSummaries.FromSqlRaw(
|
||||
@"SELECT mc.Id, mc.Name, Count(mismc.ItemsId) AS ItemCount, true AS IsSimple
|
||||
FROM MediaCollections mc
|
||||
INNER JOIN SimpleMediaCollections smc ON smc.Id = mc.Id
|
||||
LEFT OUTER JOIN MediaItemSimpleMediaCollection mismc ON mismc.SimpleMediaCollectionsId = mc.Id
|
||||
WHERE mc.Name LIKE {0}
|
||||
GROUP BY mc.Id, mc.Name
|
||||
UNION ALL
|
||||
SELECT mc.Id, mc.Name, Count(mi.Id) AS ItemCount, false AS IsSimple
|
||||
FROM MediaCollections mc
|
||||
INNER JOIN TelevisionMediaCollections tmc ON tmc.Id = mc.Id
|
||||
LEFT OUTER JOIN MediaItems mi ON (tmc.SeasonNumber IS NULL OR mi.Metadata_SeasonNumber = tmc.SeasonNumber)
|
||||
AND mi.Metadata_Title = tmc.ShowTitle
|
||||
WHERE mc.Name LIKE {0}
|
||||
GROUP BY mc.Id, mc.Name",
|
||||
$"%{searchString}%").ToListAsync();
|
||||
|
||||
public Task<Option<List<MediaItem>>> GetItems(int id) =>
|
||||
Get(id).MapT(
|
||||
collection => collection switch
|
||||
{
|
||||
SimpleMediaCollection s => SimpleItems(s),
|
||||
TelevisionMediaCollection t => TelevisionItems(t)
|
||||
}).Bind(x => x.Sequence());
|
||||
|
||||
public Task<Option<List<MediaItem>>> GetSimpleMediaCollectionItems(int id) =>
|
||||
GetSimpleMediaCollection(id).MapT(SimpleItems).Bind(x => x.Sequence());
|
||||
|
||||
public Task<Option<List<MediaItem>>> GetTelevisionMediaCollectionItems(int id) =>
|
||||
GetTelevisionMediaCollection(id).MapT(TelevisionItems).Bind(x => x.Sequence());
|
||||
|
||||
public Task Update(SimpleMediaCollection collection)
|
||||
{
|
||||
_dbContext.SimpleMediaCollections.Update(collection);
|
||||
return _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task InsertOrIgnore(TelevisionMediaCollection collection)
|
||||
{
|
||||
if (!_dbContext.TelevisionMediaCollections.Any(
|
||||
existing => existing.ShowTitle == collection.ShowTitle &&
|
||||
existing.SeasonNumber == collection.SeasonNumber))
|
||||
{
|
||||
await _dbContext.TelevisionMediaCollections.AddAsync(collection);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public Task<Unit> ReplaceItems(int collectionId, List<MediaItem> mediaItems) =>
|
||||
GetSimpleMediaCollection(collectionId).IfSomeAsync(
|
||||
async c =>
|
||||
{
|
||||
await SimpleItems(c);
|
||||
|
||||
c.Items.Clear();
|
||||
foreach (MediaItem mediaItem in mediaItems)
|
||||
{
|
||||
c.Items.Add(mediaItem);
|
||||
}
|
||||
|
||||
_dbContext.SimpleMediaCollections.Update(c);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
});
|
||||
|
||||
public async Task Delete(int mediaCollectionId)
|
||||
{
|
||||
MediaCollection mediaCollection = await _dbContext.MediaCollections.FindAsync(mediaCollectionId);
|
||||
_dbContext.MediaCollections.Remove(mediaCollection);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteEmptyTelevisionCollections()
|
||||
{
|
||||
List<int> ids = await _dbContext.GenericIntegerIds.FromSqlRaw(
|
||||
@"SELECT mc.Id FROM MediaCollections mc
|
||||
INNER JOIN TelevisionMediaCollections t on mc.Id = t.Id
|
||||
WHERE NOT EXISTS
|
||||
(SELECT 1 FROM MediaItems mi WHERE t.ShowTitle = mi.Metadata_Title AND (t.SeasonNumber IS NULL OR t.SeasonNumber = mi.Metadata_SeasonNumber))")
|
||||
.Map(i => i.Id)
|
||||
.ToListAsync();
|
||||
|
||||
List<MediaCollection> toDelete =
|
||||
await _dbContext.MediaCollections.Where(mc => ids.Contains(mc.Id)).ToListAsync();
|
||||
_dbContext.MediaCollections.RemoveRange(toDelete);
|
||||
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private async Task<List<MediaItem>> SimpleItems(SimpleMediaCollection collection)
|
||||
{
|
||||
await _dbContext.Entry(collection).Collection(c => c.Items).LoadAsync();
|
||||
return collection.Items.ToList();
|
||||
}
|
||||
|
||||
private Task<List<MediaItem>> TelevisionItems(TelevisionMediaCollection collection) =>
|
||||
_dbContext.MediaItems
|
||||
.Filter(c => c.Metadata.Title == collection.ShowTitle)
|
||||
.Filter(c => collection.SeasonNumber == null || c.Metadata.SeasonNumber == collection.SeasonNumber)
|
||||
.ToListAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using LanguageExt;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using static LanguageExt.Prelude;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
{
|
||||
public class MediaItemRepository : IMediaItemRepository
|
||||
{
|
||||
private readonly TvContext _dbContext;
|
||||
|
||||
public MediaItemRepository(TvContext dbContext) => _dbContext = dbContext;
|
||||
|
||||
public async Task<int> Add(MediaItem mediaItem)
|
||||
{
|
||||
await _dbContext.MediaItems.AddAsync(mediaItem);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return mediaItem.Id;
|
||||
}
|
||||
|
||||
public Task<Option<MediaItem>> Get(int id) =>
|
||||
_dbContext.MediaItems.SingleOrDefaultAsync(i => i.Id == id).Map(Optional);
|
||||
|
||||
public Task<List<MediaItem>> GetAll() => _dbContext.MediaItems.ToListAsync();
|
||||
|
||||
public Task<List<MediaItem>> GetAll(MediaType mediaType) =>
|
||||
_dbContext.MediaItems
|
||||
.Include(i => i.Source)
|
||||
.Filter(i => i.Metadata.MediaType == mediaType)
|
||||
.ToListAsync();
|
||||
|
||||
public Task<List<MediaItem>> GetAllByMediaSourceId(int mediaSourceId) =>
|
||||
_dbContext.MediaItems
|
||||
.Filter(i => i.MediaSourceId == mediaSourceId)
|
||||
.ToListAsync();
|
||||
|
||||
public async Task Update(MediaItem mediaItem)
|
||||
{
|
||||
_dbContext.MediaItems.Update(mediaItem);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task Delete(int mediaItemId)
|
||||
{
|
||||
MediaItem mediaItem = await _dbContext.MediaItems.FindAsync(mediaItemId);
|
||||
_dbContext.MediaItems.Remove(mediaItem);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using LanguageExt;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using static LanguageExt.Prelude;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
{
|
||||
public class MediaSourceRepository : IMediaSourceRepository
|
||||
{
|
||||
private readonly TvContext _dbContext;
|
||||
|
||||
public MediaSourceRepository(TvContext dbContext) => _dbContext = dbContext;
|
||||
|
||||
public async Task<LocalMediaSource> Add(LocalMediaSource localMediaSource)
|
||||
{
|
||||
await _dbContext.LocalMediaSources.AddAsync(localMediaSource);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return localMediaSource;
|
||||
}
|
||||
|
||||
public async Task<PlexMediaSource> Add(PlexMediaSource plexMediaSource)
|
||||
{
|
||||
await _dbContext.PlexMediaSources.AddAsync(plexMediaSource);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return plexMediaSource;
|
||||
}
|
||||
|
||||
public async Task<List<MediaSource>> GetAll()
|
||||
{
|
||||
List<MediaSource> all = await _dbContext.MediaSources.ToListAsync();
|
||||
foreach (PlexMediaSource plex in all.OfType<PlexMediaSource>())
|
||||
{
|
||||
await _dbContext.Entry(plex).Collection(p => p.Connections).LoadAsync();
|
||||
}
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
public Task<List<PlexMediaSource>> GetAllPlex() =>
|
||||
_dbContext.PlexMediaSources
|
||||
.Include(p => p.Connections)
|
||||
.ToListAsync();
|
||||
|
||||
public Task<Option<MediaSource>> Get(int id) =>
|
||||
_dbContext.MediaSources
|
||||
.SingleOrDefaultAsync(s => s.Id == id)
|
||||
.Map(Optional);
|
||||
|
||||
public Task<Option<PlexMediaSource>> GetPlex(int id) =>
|
||||
_dbContext.PlexMediaSources
|
||||
.Include(p => p.Connections)
|
||||
.Include(p => p.Libraries)
|
||||
.SingleOrDefaultAsync(p => p.Id == id)
|
||||
.Map(Optional);
|
||||
|
||||
public Task<int> CountMediaItems(int id) =>
|
||||
_dbContext.MediaItems.CountAsync(i => i.MediaSourceId == id);
|
||||
|
||||
public async Task Update(PlexMediaSource plexMediaSource)
|
||||
{
|
||||
_dbContext.PlexMediaSources.Update(plexMediaSource);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task Delete(int id)
|
||||
{
|
||||
MediaSource mediaSource = await _dbContext.MediaSources.FindAsync(id);
|
||||
_dbContext.MediaSources.Remove(mediaSource);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using LanguageExt;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using static LanguageExt.Prelude;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
{
|
||||
public class PlayoutRepository : IPlayoutRepository
|
||||
{
|
||||
private readonly TvContext _dbContext;
|
||||
|
||||
public PlayoutRepository(TvContext dbContext) => _dbContext = dbContext;
|
||||
|
||||
public async Task<Playout> Add(Playout playout)
|
||||
{
|
||||
await _dbContext.Playouts.AddAsync(playout);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return playout;
|
||||
}
|
||||
|
||||
public Task<Option<Playout>> Get(int id) =>
|
||||
_dbContext.Playouts.SingleOrDefaultAsync(p => p.Id == id).Map(Optional);
|
||||
|
||||
public async Task<Option<Playout>> GetFull(int id) =>
|
||||
await _dbContext.Playouts
|
||||
.Include(p => p.Channel)
|
||||
.Include(p => p.Items)
|
||||
.Include(p => p.ProgramScheduleAnchors)
|
||||
.Include(p => p.ProgramSchedule)
|
||||
.ThenInclude(ps => ps.Items)
|
||||
.ThenInclude(psi => psi.MediaCollection)
|
||||
.OrderBy(p => p.Id) // https://github.com/dotnet/efcore/issues/22579#issuecomment-694772289
|
||||
.SingleOrDefaultAsync(p => p.Id == id);
|
||||
|
||||
public async Task<Option<PlayoutItem>> GetPlayoutItem(int channelId, DateTimeOffset now)
|
||||
{
|
||||
var p1 = new SqliteParameter("channelId", channelId);
|
||||
var p2 = new SqliteParameter("now", now);
|
||||
return await _dbContext.PlayoutItems
|
||||
.FromSqlRaw(
|
||||
"select i.* from playoutitems i inner join playouts p on i.playoutid = p.id where p.channelid = @channelId and i.start <= @now and i.finish > @now",
|
||||
p1,
|
||||
p2)
|
||||
.Include(i => i.MediaItem)
|
||||
.AsNoTracking()
|
||||
.SingleOrDefaultAsync();
|
||||
}
|
||||
|
||||
public Task<List<PlayoutItem>> GetPlayoutItems(int playoutId) =>
|
||||
_dbContext.PlayoutItems
|
||||
.Include(i => i.MediaItem)
|
||||
.ThenInclude(mi => mi.Metadata)
|
||||
.Filter(i => i.PlayoutId == playoutId)
|
||||
.ToListAsync();
|
||||
|
||||
public Task<List<int>> GetPlayoutIdsForMediaItems(Seq<MediaItem> mediaItems)
|
||||
{
|
||||
var ids = string.Join(", ", mediaItems.Map(mi => mi.Id));
|
||||
return _dbContext.Playouts.FromSqlRaw(
|
||||
@"SELECT DISTINCT p.* FROM Playouts p
|
||||
INNER JOIN ProgramScheduleItems psi on psi.ProgramScheduleId = p.ProgramScheduleId
|
||||
INNER JOIN SimpleMediaCollections smc on smc.Id = psi.MediaCollectionId
|
||||
INNER JOIN MediaItemSimpleMediaCollection mismc on mismc.SimpleMediaCollectionsId = smc.Id
|
||||
WHERE mismc.ItemsId in ({0})
|
||||
UNION
|
||||
SELECT DISTINCT p.* FROM Playouts p
|
||||
INNER JOIN ProgramScheduleItems psi on psi.ProgramScheduleId = p.ProgramScheduleId
|
||||
INNER JOIN TelevisionMediaCollections tmc on tmc.Id = psi.MediaCollectionId
|
||||
INNER JOIN MediaItems mi on mi.Metadata_Title = tmc.ShowTitle and (tmc.SeasonNumber is null or tmc.SeasonNumber = mi.Metadata_SeasonNumber)
|
||||
WHERE mi.Id in ({0})",
|
||||
ids).Select(p => p.Id).ToListAsync();
|
||||
}
|
||||
|
||||
public Task<List<Playout>> GetAll() =>
|
||||
_dbContext.Playouts
|
||||
.Include(p => p.Channel)
|
||||
.Include(p => p.ProgramSchedule)
|
||||
.ToListAsync();
|
||||
|
||||
public async Task Update(Playout playout)
|
||||
{
|
||||
_dbContext.Playouts.Update(playout);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task Delete(int playoutId)
|
||||
{
|
||||
Playout playout = await _dbContext.Playouts.FindAsync(playoutId);
|
||||
_dbContext.Playouts.Remove(playout);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using LanguageExt;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using static LanguageExt.Prelude;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
{
|
||||
public class ProgramScheduleRepository : IProgramScheduleRepository
|
||||
{
|
||||
private readonly TvContext _dbContext;
|
||||
|
||||
public ProgramScheduleRepository(TvContext dbContext) => _dbContext = dbContext;
|
||||
|
||||
public async Task<ProgramSchedule> Add(ProgramSchedule programSchedule)
|
||||
{
|
||||
await _dbContext.ProgramSchedules.AddAsync(programSchedule);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
return programSchedule;
|
||||
}
|
||||
|
||||
public Task<Option<ProgramSchedule>> Get(int id) =>
|
||||
_dbContext.ProgramSchedules.SingleOrDefaultAsync(s => s.Id == id).Map(Optional);
|
||||
|
||||
public async Task<Option<ProgramSchedule>> GetWithPlayouts(int id) =>
|
||||
await _dbContext.ProgramSchedules
|
||||
.Include(ps => ps.Items)
|
||||
.Include(ps => ps.Playouts)
|
||||
.SingleOrDefaultAsync(ps => ps.Id == id);
|
||||
|
||||
public Task<List<ProgramSchedule>> GetAll() =>
|
||||
_dbContext.ProgramSchedules.ToListAsync();
|
||||
|
||||
public async Task Update(ProgramSchedule programSchedule)
|
||||
{
|
||||
_dbContext.ProgramSchedules.Update(programSchedule);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
await _dbContext.Entry(programSchedule).Collection(s => s.Items).Query().Include(i => i.MediaCollection)
|
||||
.LoadAsync();
|
||||
await _dbContext.Entry(programSchedule).Collection(s => s.Playouts).LoadAsync();
|
||||
}
|
||||
|
||||
public async Task Delete(int programScheduleId)
|
||||
{
|
||||
ProgramSchedule programSchedule = await _dbContext.ProgramSchedules.FindAsync(programScheduleId);
|
||||
_dbContext.ProgramSchedules.Remove(programSchedule);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<Option<List<ProgramScheduleItem>>> GetItems(int programScheduleId)
|
||||
{
|
||||
Option<ProgramSchedule> maybeSchedule = await Get(programScheduleId);
|
||||
return await maybeSchedule.Map(
|
||||
async programSchedule =>
|
||||
{
|
||||
await _dbContext.Entry(programSchedule).Collection(s => s.Items).LoadAsync();
|
||||
await _dbContext.Entry(programSchedule).Collection(s => s.Items).Query()
|
||||
.Include(i => i.MediaCollection).LoadAsync();
|
||||
return programSchedule.Items;
|
||||
}).Sequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using LanguageExt;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using static LanguageExt.Prelude;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
{
|
||||
public class ResolutionRepository : IResolutionRepository
|
||||
{
|
||||
private readonly TvContext _dbContext;
|
||||
|
||||
public ResolutionRepository(TvContext dbContext) => _dbContext = dbContext;
|
||||
|
||||
public Task<Option<Resolution>> Get(int id) =>
|
||||
_dbContext.Resolutions.SingleOrDefaultAsync(r => r.Id == id).Map(Optional);
|
||||
|
||||
public Task<List<Resolution>> GetAll() =>
|
||||
_dbContext.Resolutions.ToListAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using ErsatzTV.Core.AggregateModels;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data
|
||||
{
|
||||
public class TvContext : DbContext
|
||||
{
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
|
||||
public TvContext(DbContextOptions<TvContext> options, ILoggerFactory loggerFactory)
|
||||
: base(options) =>
|
||||
_loggerFactory = loggerFactory;
|
||||
|
||||
public DbSet<ConfigElement> ConfigElements { get; set; }
|
||||
public DbSet<Channel> Channels { get; set; }
|
||||
public DbSet<MediaSource> MediaSources { get; set; }
|
||||
public DbSet<LocalMediaSource> LocalMediaSources { get; set; }
|
||||
public DbSet<PlexMediaSource> PlexMediaSources { get; set; }
|
||||
public DbSet<MediaItem> MediaItems { get; set; }
|
||||
public DbSet<MediaCollection> MediaCollections { get; set; }
|
||||
public DbSet<SimpleMediaCollection> SimpleMediaCollections { get; set; }
|
||||
public DbSet<TelevisionMediaCollection> TelevisionMediaCollections { get; set; }
|
||||
public DbSet<ProgramSchedule> ProgramSchedules { get; set; }
|
||||
public DbSet<Playout> Playouts { get; set; }
|
||||
public DbSet<PlayoutItem> PlayoutItems { get; set; }
|
||||
public DbSet<PlayoutProgramScheduleAnchor> PlayoutProgramScheduleItemAnchors { get; set; }
|
||||
public DbSet<FFmpegProfile> FFmpegProfiles { get; set; }
|
||||
public DbSet<Resolution> Resolutions { get; set; }
|
||||
|
||||
// support raw sql queries
|
||||
public DbSet<MediaCollectionSummary> MediaCollectionSummaries { get; set; }
|
||||
public DbSet<GenericIntegerId> GenericIntegerIds { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) =>
|
||||
optionsBuilder.UseLoggerFactory(_loggerFactory);
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
builder.ApplyConfigurationsFromAssembly(typeof(TvContext).Assembly);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user