| 123456789101112131415161718192021222324252627282930313233 |
- using Application.Abstractions.Data;
- using Application.Abstractions.Messaging;
- using Microsoft.EntityFrameworkCore;
- namespace Application.Features.Api.Stocks.Watch.IsWatching;
- /// <summary>회원이 관심 등록한 코드 집합을 조회해 요청 코드별 true/false 맵을 반환 (IsFollowing 패턴).</summary>
- internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Response>
- {
- // 방어적 상한 — 엔드포인트에서도 Take(100) 하지만 Handler 계층 자체도 무방비가 되지 않도록 (GetQuotes 패턴)
- public const int MaxCodes = 100;
- public async Task<Response> Handle(Query request, CancellationToken ct)
- {
- var codes = request.Codes.Select(c => c.Trim()).Where(c => c.Length > 0).Distinct().Take(MaxCodes).ToArray();
- if (codes.Length == 0)
- {
- return new Response { Map = new Dictionary<string, bool>() };
- }
- var watched = await db.StockWatch.AsNoTracking()
- .Where(w => w.MemberID == request.MemberID && codes.Contains(w.StockCode))
- .Select(w => w.StockCode)
- .ToListAsync(ct);
- var watchedSet = watched.ToHashSet();
- var map = codes.ToDictionary(c => c, c => watchedSet.Contains(c));
- return new Response { Map = map };
- }
- }
|