feat(rank): viewer repo LoadForRankProgressAsync
Split-query load of Classes (for class XP) + RankProgress (for rank grant) so RankBattleController.Finish uses a single viewer read. Test factory's ReferenceDataImporter.ImportAllAsync already seeds RankInfo — no test helper needed. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,14 @@ public interface IViewerRepository
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Task<Models.Viewer?> LoadForBattleXpGrantAsync(long viewerId, CancellationToken ct = default);
|
Task<Models.Viewer?> LoadForBattleXpGrantAsync(long viewerId, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load a viewer with the joins <see cref="Controllers.RankBattleController"/>'s <c>Finish</c>
|
||||||
|
/// needs: Classes (for the class-XP grant) + RankProgress (for the rank grant). Split-query
|
||||||
|
/// per <c>project_ef_split_query</c> to avoid the cartesian explosion when both nav
|
||||||
|
/// collections are populated on the same viewer.
|
||||||
|
/// </summary>
|
||||||
|
Task<Models.Viewer?> LoadForRankProgressAsync(long viewerId, CancellationToken ct = default);
|
||||||
|
|
||||||
/// <summary>Sets Viewer.GuildId to <paramref name="guildId"/>. No-op if the viewer does not exist.</summary>
|
/// <summary>Sets Viewer.GuildId to <paramref name="guildId"/>. No-op if the viewer does not exist.</summary>
|
||||||
Task SetGuildIdAsync(long viewerId, int guildId, CancellationToken ct = default);
|
Task SetGuildIdAsync(long viewerId, int guildId, CancellationToken ct = default);
|
||||||
|
|
||||||
|
|||||||
@@ -281,6 +281,16 @@ public class ViewerRepository : IViewerRepository
|
|||||||
.FirstOrDefaultAsync(v => v.Id == viewerId, ct);
|
.FirstOrDefaultAsync(v => v.Id == viewerId, ct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<Models.Viewer?> LoadForRankProgressAsync(long viewerId, CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
return _dbContext.Set<Models.Viewer>()
|
||||||
|
.Include(v => v.Classes)
|
||||||
|
.ThenInclude(c => c.Class)
|
||||||
|
.Include(v => v.RankProgress)
|
||||||
|
.AsSplitQuery()
|
||||||
|
.FirstOrDefaultAsync(v => v.Id == viewerId, ct);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task SetGuildIdAsync(long viewerId, int guildId, CancellationToken ct = default)
|
public async Task SetGuildIdAsync(long viewerId, int guildId, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var viewer = await _dbContext.Set<Models.Viewer>()
|
var viewer = await _dbContext.Set<Models.Viewer>()
|
||||||
|
|||||||
Reference in New Issue
Block a user