Browse Source

use single dapper queries

pull/29/head
Jason Dove 6 years ago
parent
commit
8b860c705e
  1. 83
      ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs
  2. 54
      ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs
  3. 32
      ErsatzTV.Infrastructure/Data/SqliteTypeHandlers.cs
  4. 6
      ErsatzTV/Startup.cs

83
ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs

@ -14,8 +14,8 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
{ {
public class MediaCollectionRepository : IMediaCollectionRepository public class MediaCollectionRepository : IMediaCollectionRepository
{ {
private readonly TvContext _dbContext;
private readonly IDbConnection _dbConnection; private readonly IDbConnection _dbConnection;
private readonly TvContext _dbContext;
public MediaCollectionRepository(TvContext dbContext, IDbConnection dbConnection) public MediaCollectionRepository(TvContext dbContext, IDbConnection dbConnection)
{ {
@ -118,54 +118,79 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionShowItems(SimpleMediaCollection collection) private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionShowItems(SimpleMediaCollection collection)
{ {
var parameters = new { CollectionId = collection.Id }; var parameters = new { CollectionId = collection.Id };
IEnumerable<int> showItemIds = await _dbConnection.QueryAsync<int>( return await _dbConnection
@"select tmi.Id .QueryAsync<TelevisionEpisodeMediaItem, MediaItemStatistics, TelevisionEpisodeMetadata,
TelevisionEpisodeMediaItem>(
@"select tmi.Id, tmi.SeasonId, mi.MediaSourceId, mi.LastWriteTime, mi.Path, mi.Poster, mi.PosterLastWriteTime,
mi.Statistics_AudioCodec as AudioCodec, mi.Statistics_DisplayAspectRatio as DisplayAspectRatio, mi.Statistics_Duration as Duration, mi.Statistics_Height as Height, mi.Statistics_LastWriteTime as LastWriteTime, mi.Statistics_SampleAspectRatio as SampleAspectRatio,
mi.Statistics_VideoCodec as VideoCodec, mi.Statistics_VideoScanType as VideoScanType, mi.Statistics_Width as Width,
tem.TelevisionEpisodeId, tem.Id, tem.Season, tem.Episode, tem.Plot, tem.Aired, tem.Source, tem.LastWriteTime, tem.Title, tem.SortTitle
from TelevisionEpisodes tmi from TelevisionEpisodes tmi
inner join MediaItems mi on tmi.Id = mi.Id
inner join TelevisionEpisodeMetadata tem on tem.TelevisionEpisodeId = tmi.Id
inner join TelevisionSeasons tsn on tsn.Id = tmi.SeasonId inner join TelevisionSeasons tsn on tsn.Id = tmi.SeasonId
inner join TelevisionShows ts on ts.Id = tsn.TelevisionShowId inner join TelevisionShows ts on ts.Id = tsn.TelevisionShowId
inner join SimpleMediaCollectionShows s on s.TelevisionShowsId = ts.Id inner join SimpleMediaCollectionShows s on s.TelevisionShowsId = ts.Id
where s.SimpleMediaCollectionsId = @CollectionId", where s.SimpleMediaCollectionsId = @CollectionId",
parameters); (episode, statistics, metadata) =>
{
return await _dbContext.TelevisionEpisodeMediaItems episode.Statistics = statistics;
.AsNoTracking() episode.Metadata = metadata;
.Include(e => e.Metadata) return episode;
.Where(mi => showItemIds.Contains(mi.Id)) },
.ToListAsync(); parameters,
splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
} }
private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionSeasonItems(SimpleMediaCollection collection) private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionSeasonItems(SimpleMediaCollection collection)
{ {
var parameters = new { CollectionId = collection.Id }; var parameters = new { CollectionId = collection.Id };
IEnumerable<int> seasonItemIds = await _dbConnection.QueryAsync<int>( return await _dbConnection
@"select tmi.Id .QueryAsync<TelevisionEpisodeMediaItem, MediaItemStatistics, TelevisionEpisodeMetadata,
TelevisionEpisodeMediaItem>(
@"select tmi.Id, tmi.SeasonId, mi.MediaSourceId, mi.LastWriteTime, mi.Path, mi.Poster, mi.PosterLastWriteTime,
mi.Statistics_AudioCodec as AudioCodec, mi.Statistics_DisplayAspectRatio as DisplayAspectRatio, mi.Statistics_Duration as Duration, mi.Statistics_Height as Height, mi.Statistics_LastWriteTime as LastWriteTime, mi.Statistics_SampleAspectRatio as SampleAspectRatio,
mi.Statistics_VideoCodec as VideoCodec, mi.Statistics_VideoScanType as VideoScanType, mi.Statistics_Width as Width,
tem.TelevisionEpisodeId, tem.Id, tem.Season, tem.Episode, tem.Plot, tem.Aired, tem.Source, tem.LastWriteTime, tem.Title, tem.SortTitle
from TelevisionEpisodes tmi from TelevisionEpisodes tmi
inner join MediaItems mi on tmi.Id = mi.Id
inner join TelevisionEpisodeMetadata tem on tem.TelevisionEpisodeId = tmi.Id
inner join TelevisionSeasons tsn on tsn.Id = tmi.SeasonId inner join TelevisionSeasons tsn on tsn.Id = tmi.SeasonId
inner join SimpleMediaCollectionSeasons s on s.TelevisionSeasonsId = tsn.Id inner join SimpleMediaCollectionSeasons s on s.TelevisionSeasonsId = tsn.Id
where s.SimpleMediaCollectionsId = @CollectionId", where s.SimpleMediaCollectionsId = @CollectionId",
parameters); (episode, statistics, metadata) =>
{
return await _dbContext.TelevisionEpisodeMediaItems episode.Statistics = statistics;
.AsNoTracking() episode.Metadata = metadata;
.Include(e => e.Metadata) return episode;
.Where(mi => seasonItemIds.Contains(mi.Id)) },
.ToListAsync(); parameters,
splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
} }
private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionEpisodeItems(SimpleMediaCollection collection) private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionEpisodeItems(SimpleMediaCollection collection)
{ {
var parameters = new { CollectionId = collection.Id }; var parameters = new { CollectionId = collection.Id };
IEnumerable<int> episodeItemIds = await _dbConnection.QueryAsync<int>( return await _dbConnection
@"select s.TelevisionEpisodesId as Id .QueryAsync<TelevisionEpisodeMediaItem, MediaItemStatistics, TelevisionEpisodeMetadata,
from SimpleMediaCollectionEpisodes s TelevisionEpisodeMediaItem>(
@"select tmi.Id, tmi.SeasonId, mi.MediaSourceId, mi.LastWriteTime, mi.Path, mi.Poster, mi.PosterLastWriteTime,
mi.Statistics_AudioCodec as AudioCodec, mi.Statistics_DisplayAspectRatio as DisplayAspectRatio, mi.Statistics_Duration as Duration, mi.Statistics_Height as Height, mi.Statistics_LastWriteTime as LastWriteTime, mi.Statistics_SampleAspectRatio as SampleAspectRatio,
mi.Statistics_VideoCodec as VideoCodec, mi.Statistics_VideoScanType as VideoScanType, mi.Statistics_Width as Width,
tem.TelevisionEpisodeId, tem.Id, tem.Season, tem.Episode, tem.Plot, tem.Aired, tem.Source, tem.LastWriteTime, tem.Title, tem.SortTitle
from TelevisionEpisodes tmi
inner join MediaItems mi on tmi.Id = mi.Id
inner join TelevisionEpisodeMetadata tem on tem.TelevisionEpisodeId = tmi.Id
inner join SimpleMediaCollectionEpisodes s on s.TelevisionEpisodesId = tmi.Id
where s.SimpleMediaCollectionsId = @CollectionId", where s.SimpleMediaCollectionsId = @CollectionId",
parameters); (episode, statistics, metadata) =>
{
return await _dbContext.TelevisionEpisodeMediaItems episode.Statistics = statistics;
.AsNoTracking() episode.Metadata = metadata;
.Include(e => e.Metadata) return episode;
.Where(mi => episodeItemIds.Contains(mi.Id)) },
.ToListAsync(); parameters,
splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
} }
} }
} }

54
ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs

@ -15,8 +15,8 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
{ {
public class TelevisionRepository : ITelevisionRepository public class TelevisionRepository : ITelevisionRepository
{ {
private readonly TvContext _dbContext;
private readonly IDbConnection _dbConnection; private readonly IDbConnection _dbConnection;
private readonly TvContext _dbContext;
public TelevisionRepository(TvContext dbContext, IDbConnection dbConnection) public TelevisionRepository(TvContext dbContext, IDbConnection dbConnection)
{ {
@ -253,36 +253,52 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
public async Task<List<TelevisionEpisodeMediaItem>> GetShowItems(int televisionShowId) public async Task<List<TelevisionEpisodeMediaItem>> GetShowItems(int televisionShowId)
{ {
var parameters = new { ShowId = televisionShowId }; var parameters = new { ShowId = televisionShowId };
IEnumerable<int> showItemIds = await _dbConnection.QueryAsync<int>( return await _dbConnection
@"select tmi.Id .QueryAsync<TelevisionEpisodeMediaItem, MediaItemStatistics, TelevisionEpisodeMetadata,
TelevisionEpisodeMediaItem>(
@"select tmi.Id, tmi.SeasonId, mi.MediaSourceId, mi.LastWriteTime, mi.Path, mi.Poster, mi.PosterLastWriteTime,
mi.Statistics_AudioCodec as AudioCodec, mi.Statistics_DisplayAspectRatio as DisplayAspectRatio, mi.Statistics_Duration as Duration, mi.Statistics_Height as Height, mi.Statistics_LastWriteTime as LastWriteTime, mi.Statistics_SampleAspectRatio as SampleAspectRatio,
mi.Statistics_VideoCodec as VideoCodec, mi.Statistics_VideoScanType as VideoScanType, mi.Statistics_Width as Width,
tem.TelevisionEpisodeId, tem.Id, tem.Season, tem.Episode, tem.Plot, tem.Aired, tem.Source, tem.LastWriteTime, tem.Title, tem.SortTitle
from TelevisionEpisodes tmi from TelevisionEpisodes tmi
inner join MediaItems mi on tmi.Id = mi.Id
inner join TelevisionEpisodeMetadata tem on tem.TelevisionEpisodeId = tmi.Id
inner join TelevisionSeasons tsn on tsn.Id = tmi.SeasonId inner join TelevisionSeasons tsn on tsn.Id = tmi.SeasonId
inner join TelevisionShows ts on ts.Id = tsn.TelevisionShowId inner join TelevisionShows ts on ts.Id = tsn.TelevisionShowId
where ts.Id = @ShowId", where ts.Id = @ShowId",
parameters); (episode, statistics, metadata) =>
{
return await _dbContext.TelevisionEpisodeMediaItems episode.Statistics = statistics;
.AsNoTracking() episode.Metadata = metadata;
.Include(e => e.Metadata) return episode;
.Where(mi => showItemIds.Contains(mi.Id)) },
.ToListAsync(); parameters,
splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
} }
public async Task<List<TelevisionEpisodeMediaItem>> GetSeasonItems(int televisionSeasonId) public async Task<List<TelevisionEpisodeMediaItem>> GetSeasonItems(int televisionSeasonId)
{ {
var parameters = new { SeasonId = televisionSeasonId }; var parameters = new { SeasonId = televisionSeasonId };
IEnumerable<int> seasonItemIds = await _dbConnection.QueryAsync<int>( return await _dbConnection
@"select tmi.Id .QueryAsync<TelevisionEpisodeMediaItem, MediaItemStatistics, TelevisionEpisodeMetadata,
TelevisionEpisodeMediaItem>(
@"select tmi.Id, tmi.SeasonId, mi.MediaSourceId, mi.LastWriteTime, mi.Path, mi.Poster, mi.PosterLastWriteTime,
mi.Statistics_AudioCodec as AudioCodec, mi.Statistics_DisplayAspectRatio as DisplayAspectRatio, mi.Statistics_Duration as Duration, mi.Statistics_Height as Height, mi.Statistics_LastWriteTime as LastWriteTime, mi.Statistics_SampleAspectRatio as SampleAspectRatio,
mi.Statistics_VideoCodec as VideoCodec, mi.Statistics_VideoScanType as VideoScanType, mi.Statistics_Width as Width,
tem.TelevisionEpisodeId, tem.Id, tem.Season, tem.Episode, tem.Plot, tem.Aired, tem.Source, tem.LastWriteTime, tem.Title, tem.SortTitle
from TelevisionEpisodes tmi from TelevisionEpisodes tmi
inner join MediaItems mi on tmi.Id = mi.Id
inner join TelevisionEpisodeMetadata tem on tem.TelevisionEpisodeId = tmi.Id
inner join TelevisionSeasons tsn on tsn.Id = tmi.SeasonId inner join TelevisionSeasons tsn on tsn.Id = tmi.SeasonId
where tsn.Id = @SeasonId", where tsn.Id = @SeasonId",
parameters); (episode, statistics, metadata) =>
{
return await _dbContext.TelevisionEpisodeMediaItems episode.Statistics = statistics;
.AsNoTracking() episode.Metadata = metadata;
.Include(e => e.Metadata) return episode;
.Where(mi => seasonItemIds.Contains(mi.Id)) },
.ToListAsync(); parameters,
splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
} }
private async Task<Either<BaseError, TelevisionSeason>> AddSeason( private async Task<Either<BaseError, TelevisionSeason>> AddSeason(

32
ErsatzTV.Infrastructure/Data/SqliteTypeHandlers.cs

@ -0,0 +1,32 @@
using System;
using System.Data;
using Dapper;
namespace ErsatzTV.Infrastructure.Data
{
public abstract class SqliteTypeHandler<T> : SqlMapper.TypeHandler<T>
{
// Parameters are converted by Microsoft.Data.Sqlite
public override void SetValue(IDbDataParameter parameter, T value)
=> parameter.Value = value;
}
public class DateTimeOffsetHandler : SqliteTypeHandler<DateTimeOffset>
{
public override DateTimeOffset Parse(object value)
=> DateTimeOffset.Parse((string)value);
}
public class GuidHandler : SqliteTypeHandler<Guid>
{
public override Guid Parse(object value)
=> Guid.Parse((string)value);
}
public class TimeSpanHandler : SqliteTypeHandler<TimeSpan>
{
public override TimeSpan Parse(object value)
=> TimeSpan.Parse((string)value);
}
}

6
ErsatzTV/Startup.cs

@ -3,6 +3,7 @@ using System.Data;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Threading.Channels; using System.Threading.Channels;
using Dapper;
using ErsatzTV.Application; using ErsatzTV.Application;
using ErsatzTV.Application.Channels.Queries; using ErsatzTV.Application.Channels.Queries;
using ErsatzTV.Core; using ErsatzTV.Core;
@ -125,7 +126,10 @@ namespace ErsatzTV
services.AddDbContext<LogContext>(options => options.UseSqlite(connectionString)); services.AddDbContext<LogContext>(options => options.UseSqlite(connectionString));
services.AddTransient<IDbConnection>(_ => new SqliteConnection(connectionString)); services.AddTransient<IDbConnection>(_ => new SqliteConnection(connectionString));
SqlMapper.AddTypeHandler(new DateTimeOffsetHandler());
SqlMapper.AddTypeHandler(new GuidHandler());
SqlMapper.AddTypeHandler(new TimeSpanHandler());
services.AddMediatR(typeof(GetAllChannels).Assembly); services.AddMediatR(typeof(GetAllChannels).Assembly);
services.AddRefitClient<IPlexTvApi>() services.AddRefitClient<IPlexTvApi>()

Loading…
Cancel
Save