use dapper in a few places (#29)
* use dapper in a few places * use single dapper queries
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
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().ToView("No table or view exists for GenericIntegerId");
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
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().ToView("No table or view exists for MediaCollectionSummary");
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using ErsatzTV.Core.AggregateModels;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Data.Configurations
|
||||
{
|
||||
public class MediaItemSummaryConfiguration : IEntityTypeConfiguration<MediaItemSummary>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<MediaItemSummary> builder) =>
|
||||
builder.HasNoKey().ToView("No table or view exists for MediaItemSummary");
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Dapper;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using LanguageExt;
|
||||
@@ -12,9 +14,14 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
{
|
||||
public class MediaCollectionRepository : IMediaCollectionRepository
|
||||
{
|
||||
private readonly IDbConnection _dbConnection;
|
||||
private readonly TvContext _dbContext;
|
||||
|
||||
public MediaCollectionRepository(TvContext dbContext) => _dbContext = dbContext;
|
||||
public MediaCollectionRepository(TvContext dbContext, IDbConnection dbConnection)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_dbConnection = dbConnection;
|
||||
}
|
||||
|
||||
public async Task<SimpleMediaCollection> Add(SimpleMediaCollection collection)
|
||||
{
|
||||
@@ -110,61 +117,80 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
|
||||
private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionShowItems(SimpleMediaCollection collection)
|
||||
{
|
||||
// TODO: would be nice to get the media items in one go, but ef...
|
||||
List<int> showItemIds = await _dbContext.GenericIntegerIds.FromSqlRaw(
|
||||
@"select tmi.Id
|
||||
var parameters = new { CollectionId = collection.Id };
|
||||
return await _dbConnection
|
||||
.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
|
||||
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 TelevisionShows ts on ts.Id = tsn.TelevisionShowId
|
||||
inner join SimpleMediaCollectionShows s on s.TelevisionShowsId = ts.Id
|
||||
where s.SimpleMediaCollectionsId = {0}",
|
||||
collection.Id)
|
||||
.Select(i => i.Id)
|
||||
.ToListAsync();
|
||||
|
||||
return await _dbContext.TelevisionEpisodeMediaItems
|
||||
.AsNoTracking()
|
||||
.Include(e => e.Metadata)
|
||||
.Where(mi => showItemIds.Contains(mi.Id))
|
||||
.ToListAsync();
|
||||
where s.SimpleMediaCollectionsId = @CollectionId",
|
||||
(episode, statistics, metadata) =>
|
||||
{
|
||||
episode.Statistics = statistics;
|
||||
episode.Metadata = metadata;
|
||||
return episode;
|
||||
},
|
||||
parameters,
|
||||
splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
|
||||
}
|
||||
|
||||
private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionSeasonItems(SimpleMediaCollection collection)
|
||||
{
|
||||
// TODO: would be nice to get the media items in one go, but ef...
|
||||
List<int> seasonItemIds = await _dbContext.GenericIntegerIds.FromSqlRaw(
|
||||
@"select tmi.Id
|
||||
var parameters = new { CollectionId = collection.Id };
|
||||
return await _dbConnection
|
||||
.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
|
||||
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 SimpleMediaCollectionSeasons s on s.TelevisionSeasonsId = tsn.Id
|
||||
where s.SimpleMediaCollectionsId = {0}",
|
||||
collection.Id)
|
||||
.Select(i => i.Id)
|
||||
.ToListAsync();
|
||||
|
||||
return await _dbContext.TelevisionEpisodeMediaItems
|
||||
.AsNoTracking()
|
||||
.Include(e => e.Metadata)
|
||||
.Where(mi => seasonItemIds.Contains(mi.Id))
|
||||
.ToListAsync();
|
||||
where s.SimpleMediaCollectionsId = @CollectionId",
|
||||
(episode, statistics, metadata) =>
|
||||
{
|
||||
episode.Statistics = statistics;
|
||||
episode.Metadata = metadata;
|
||||
return episode;
|
||||
},
|
||||
parameters,
|
||||
splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
|
||||
}
|
||||
|
||||
private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionEpisodeItems(SimpleMediaCollection collection)
|
||||
{
|
||||
// TODO: would be nice to get the media items in one go, but ef...
|
||||
List<int> episodeItemIds = await _dbContext.GenericIntegerIds.FromSqlRaw(
|
||||
@"select s.TelevisionEpisodesId as Id
|
||||
from SimpleMediaCollectionEpisodes s
|
||||
where s.SimpleMediaCollectionsId = {0}",
|
||||
collection.Id)
|
||||
.Select(i => i.Id)
|
||||
.ToListAsync();
|
||||
|
||||
return await _dbContext.TelevisionEpisodeMediaItems
|
||||
.AsNoTracking()
|
||||
.Include(e => e.Metadata)
|
||||
.Where(mi => episodeItemIds.Contains(mi.Id))
|
||||
.ToListAsync();
|
||||
var parameters = new { CollectionId = collection.Id };
|
||||
return await _dbConnection
|
||||
.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
|
||||
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",
|
||||
(episode, statistics, metadata) =>
|
||||
{
|
||||
episode.Statistics = statistics;
|
||||
episode.Metadata = metadata;
|
||||
return episode;
|
||||
},
|
||||
parameters,
|
||||
splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Dapper;
|
||||
using ErsatzTV.Core;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
@@ -13,9 +15,14 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
{
|
||||
public class TelevisionRepository : ITelevisionRepository
|
||||
{
|
||||
private readonly IDbConnection _dbConnection;
|
||||
private readonly TvContext _dbContext;
|
||||
|
||||
public TelevisionRepository(TvContext dbContext) => _dbContext = dbContext;
|
||||
public TelevisionRepository(TvContext dbContext, IDbConnection dbConnection)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_dbConnection = dbConnection;
|
||||
}
|
||||
|
||||
public async Task<bool> Update(TelevisionShow show)
|
||||
{
|
||||
@@ -245,41 +252,53 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
|
||||
|
||||
public async Task<List<TelevisionEpisodeMediaItem>> GetShowItems(int televisionShowId)
|
||||
{
|
||||
// TODO: would be nice to get the media items in one go, but ef...
|
||||
List<int> showItemIds = await _dbContext.GenericIntegerIds.FromSqlRaw(
|
||||
@"select tmi.Id
|
||||
var parameters = new { ShowId = televisionShowId };
|
||||
return await _dbConnection
|
||||
.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
|
||||
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 TelevisionShows ts on ts.Id = tsn.TelevisionShowId
|
||||
where ts.Id = {0}",
|
||||
televisionShowId)
|
||||
.Select(i => i.Id)
|
||||
.ToListAsync();
|
||||
|
||||
return await _dbContext.TelevisionEpisodeMediaItems
|
||||
.AsNoTracking()
|
||||
.Include(e => e.Metadata)
|
||||
.Where(mi => showItemIds.Contains(mi.Id))
|
||||
.ToListAsync();
|
||||
where ts.Id = @ShowId",
|
||||
(episode, statistics, metadata) =>
|
||||
{
|
||||
episode.Statistics = statistics;
|
||||
episode.Metadata = metadata;
|
||||
return episode;
|
||||
},
|
||||
parameters,
|
||||
splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
|
||||
}
|
||||
|
||||
public async Task<List<TelevisionEpisodeMediaItem>> GetSeasonItems(int televisionSeasonId)
|
||||
{
|
||||
// TODO: would be nice to get the media items in one go, but ef...
|
||||
List<int> seasonItemIds = await _dbContext.GenericIntegerIds.FromSqlRaw(
|
||||
@"select tmi.Id
|
||||
var parameters = new { SeasonId = televisionSeasonId };
|
||||
return await _dbConnection
|
||||
.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
|
||||
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
|
||||
where tsn.Id = {0}",
|
||||
televisionSeasonId)
|
||||
.Select(i => i.Id)
|
||||
.ToListAsync();
|
||||
|
||||
return await _dbContext.TelevisionEpisodeMediaItems
|
||||
.AsNoTracking()
|
||||
.Include(e => e.Metadata)
|
||||
.Where(mi => seasonItemIds.Contains(mi.Id))
|
||||
.ToListAsync();
|
||||
where tsn.Id = @SeasonId",
|
||||
(episode, statistics, metadata) =>
|
||||
{
|
||||
episode.Statistics = statistics;
|
||||
episode.Metadata = metadata;
|
||||
return episode;
|
||||
},
|
||||
parameters,
|
||||
splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
|
||||
}
|
||||
|
||||
private async Task<Either<BaseError, TelevisionSeason>> AddSeason(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using ErsatzTV.Core.AggregateModels;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -34,11 +33,6 @@ namespace ErsatzTV.Infrastructure.Data
|
||||
public DbSet<TelevisionShowMetadata> TelevisionShowMetadata { get; set; }
|
||||
public DbSet<TelevisionSeason> TelevisionSeasons { get; set; }
|
||||
|
||||
// support raw sql queries
|
||||
public DbSet<MediaCollectionSummary> MediaCollectionSummaries { get; set; }
|
||||
public DbSet<GenericIntegerId> GenericIntegerIds { get; set; }
|
||||
public DbSet<MediaItemSummary> MediaItemSummaries { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) =>
|
||||
optionsBuilder.UseLoggerFactory(_loggerFactory);
|
||||
|
||||
@@ -46,10 +40,6 @@ namespace ErsatzTV.Infrastructure.Data
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
|
||||
builder.Ignore<MediaCollectionSummary>();
|
||||
builder.Ignore<GenericIntegerId>();
|
||||
builder.Ignore<MediaItemSummary>();
|
||||
|
||||
builder.ApplyConfigurationsFromAssembly(typeof(TvContext).Assembly);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.0.78" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
||||
Reference in New Issue
Block a user