using Dapper; using ErsatzTV.Application.MediaItems; using ErsatzTV.Infrastructure.Data; using Microsoft.EntityFrameworkCore; namespace ErsatzTV.Application.Search; public class SearchArtistsHandler : IRequestHandler> { private readonly IDbContextFactory _dbContextFactory; public SearchArtistsHandler(IDbContextFactory dbContextFactory) => _dbContextFactory = dbContextFactory; public async Task> Handle(SearchArtists request, CancellationToken cancellationToken) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); return await dbContext.Connection.QueryAsync( @"SELECT Artist.Id, AM.Title FROM Artist INNER JOIN ArtistMetadata AM on AM.ArtistId = Artist.Id WHERE AM.Title LIKE @Title ORDER BY AM.Title LIMIT 10 COLLATE NOCASE", new { Title = $"%{request.Query}%" }) .Map(list => list.Bind(a => ToNamedMediaItem(a)).ToList()); } private static Option ToNamedMediaItem(Artist artist) { if (string.IsNullOrWhiteSpace(artist.Title)) { return Option.None; } return new NamedMediaItemViewModel(artist.Id, artist.Title); } public record Artist(int Id, string Title) { public Artist() : this(default, default) { } } }