using Dapper; using Femto.Modules.Blog.Contracts.Dto; using Femto.Modules.Blog.Infrastructure.DbConnection; using MediatR; using Microsoft.Data.SqlClient; namespace Femto.Modules.Blog.Domain.Posts.Commands.GetAuthorPosts; public class GetAuthorPostsQueryHandler(IDbConnectionFactory connectionFactory) : IRequestHandler> { public async Task> Handle( GetAuthorPostsQuery query, CancellationToken cancellationToken ) { using var conn = connectionFactory.GetConnection(); var sql = $$""" with post_page as ( select * from blog.post where blog.post.author_id = @authorId and (@cursor is null or blog.post.id < @cursor) order by blog.post.id desc limit @count ) select p.id as PostId, p.content as Content, pm.url as MediaUrl from post_page p left join blog.post_media pm on pm.post_id = p.id order by p.id desc """; var result = await conn.QueryAsync( sql, new { authorId = query.AuthorId, cursor = query.Cursor, count = query.Count } ); return result .GroupBy(row => row.PostId) .Select(group => new GetAuthorPostsDto( group.Key, group.First().Content, group .Select(row => row.MediaUrl) .OfType() .Select(url => new GetAuthorPostsMediaDto(new Uri(url))) .ToList() )) .ToList(); } internal class QueryResult { public Guid PostId { get; set; } public string Content { get; set; } public string? MediaUrl { get; set; } } }