我有两个字符串数组,其中包含请求中的冠军名称。我想计算其中一支球队包含 request.TeamChampionNames 中的冠军而另一支球队包含 request.EnemyChampionNames 中的冠军的比赛的胜负。一场比赛只有 2 支球队。每个冠军都是独一无二的。是否可以重写此查询,以便所有工作都在数据库端执行?
代码:
var matches = await
(from match in _context.Set<Match>()
let participants = match.Teams
.SelectMany(x => x.Participants)
.Select(p => new { p.ChampionName, p.Win })
let teammates = participants.Where(participant => request.TeamChampionNames.Contains(participant.ChampionName))
let enemies = participants.Where(participant => request.EnemyChampionNames.Contains(participant.ChampionName))
where teammates.Count() == request.TeamChampionNames.Count()
&& enemies.Count() == request.EnemyChampionNames.Count()
select teammates.First().Win // selecting whether teammates win
)
.ToListAsync(cancellationToken);
var winRates = new TeamWinRateResponse
{
Wins = matches.Count(hasWon => hasWon),
Loses = matches.Count(hasWon => !hasWon)
};
型号:
public record WinRateGetQuery : IRequest<TeamWinRateResponse>
{
public required IEnumerable<string> TeamChampionNames { get; init; }
public required IEnumerable<string> EnemyChampionNames { get; init; }
}
public class Match
{
public string Id { get; set; } = null!;
public virtual ICollection<MatchTeam> Teams { get; set; } = new HashSet<MatchTeam>();
}
public class MatchParticipant
{
public Guid Id { get; set; }
public string ChampionName { get; set; } = string.Empty;
public bool Win { get; set; }
public string TeamId { get; set; } = null!;
public virtual MatchTeam Team { get; set; } = null!;
}
public class MatchTeam
{
public string Id { get; set; } = null!;
public bool Win { get; set; }
public string MatchId { get; set; } = null!;
public virtual Match Match { get; set; } = null!;
public virtual ICollection<MatchParticipant> Participants { get; set; } = new HashSet<MatchParticipant>();
}
只需将整个事情合并到一个查询中,而不是做
ToListAsync
。
var winRates = (
from match in _context.Set<Match>()
let participants = match.Teams
.SelectMany(x => x.Participants)
.Select(p => new { p.ChampionName, p.Win })
let teammates = participants.Where(participant => request.TeamChampionNames.Contains(participant.ChampionName))
let enemies = participants.Where(participant => request.EnemyChampionNames.Contains(participant.ChampionName))
where teammates.Count() == request.TeamChampionNames.Count()
&& enemies.Count() == request.EnemyChampionNames.Count()
select teammates.First().Win // selecting whether teammates win
group by 1 into matches // use a constant to do GROUP BY ()
select new TeamWinRateResponse
{
Wins = matches.Count(hasWon => hasWon),
Loses = matches.Count(hasWon => !hasWon)
}
).FirstAsync(cancellationToken);