健身房场景下EF Core关联查询:按训练场次筛选当日参训学员
EF Core 查询指定日期参训学员解决方案
1. 关联关系说明
现有实体的导航属性已经满足团队预约场景的查询需求,无需额外新增学员到训练场次的直接关联:
- Session 持有 Team 导航属性,可关联到对应预约队伍
- Team 持有 Students 集合导航属性,可关联到队伍下所有学员
如果后续需要支持学员单独预约场次的需求,再考虑新增 Student 和 Session 的多对多关联即可。
2. 实现代码
方案1:从场次出发查询(可同时返回场次+学员信息,适合列表多字段展示)
// 传入的指定查询日期 DateTime targetDate = new DateTime(2021, 11, 6); // 定义接收结果的DTO,也可以用匿名类 public class TrainingStudentDto { public int SessionId { get; set; } public string SessionName { get; set; } public DateTime SessionDate { get; set; } public int StudentId { get; set; } public string StudentFullName { get; set; } public string TeamName { get; set; } } var result = await _dbContext.Sessions // 过滤有效场次:未删除、已激活、日期匹配 .Where(s => s.IsDeleted == false && s.IsActive == true && s.StartDate.HasValue && s.StartDate.Value.Date == targetDate.Date) // 加载关联的队伍和有效学员数据 .Include(s => s.Team) .ThenInclude(t => t.Students.Where(stu => stu.IsDeleted == false && stu.IsActive == true)) // 扁平化结果,映射到DTO .SelectMany(s => s.Team.Students.Select(stu => new TrainingStudentDto { SessionId = s.Id, SessionName = s.Name, SessionDate = s.StartDate.Value, StudentId = stu.Id, StudentFullName = $"{stu.FirstName} {stu.Surname}", TeamName = s.Team.Name })) .ToListAsync();
方案2:从学员出发查询(仅返回学员列表)
DateTime targetDate = new DateTime(2021, 11, 6); var students = await _dbContext.Students // 过滤有效学员 .Where(s => s.IsDeleted == false && s.IsActive == true && s.TeamId.HasValue // 关联队伍的对应场次满足日期要求 && _dbContext.Sessions.Any(se => se.Id == s.Team.SessionId && se.IsDeleted == false && se.IsActive == true && se.StartDate.HasValue && se.StartDate.Value.Date == targetDate.Date)) .ToListAsync();
3. 注意事项
- 日期比较时使用
.Date属性取日期部分,避免StartTime带的时间参数导致匹配失败 - 可根据页面实际展示的字段调整DTO的属性,减少不必要的字段查询提升性能
- 如果需要处理跨天的场次,可调整Where条件里的日期判断逻辑,改为判断targetDate是否在StartDate和EndDate范围内
内容的提问来源于stack exchange,提问作者dotnetdevcsharp
相关产品推荐
相关产品推荐

