如何在Linq查询中替换DateTime.Today为自定义日期获取缺勤员工列表?
解决指定日期员工缺勤查询问题
你的核心问题是错误使用DefaultIfEmpty和日期比较逻辑,同时忽略了AttendanceDate可能包含时间部分导致的匹配失败。以下是修正方案:
问题分析
- 原代码中
eGroup.Where(a => a.AttendanceDate == DateTime.Today)能正常工作,是因为DateTime.Today返回的是日期为当天、时间为00:00:00的DateTime值,刚好匹配考勤记录的日期存储格式。 - 你尝试的两种写法存在语法错误:
date.DefaultIfEmpty():DefaultIfEmpty是LINQ对集合的扩展方法,不能直接用于单个DateTime变量((date).Year, (date).Month, (date).Day):这是C#元组语法,无法直接与DateTime类型的AttendanceDate做相等比较
修正后的代码
public async Task<IEnumerable<AbsentReportsViewModel>> GetAllAbsentEmpAsync(DateTime date) { // 提取传入日期的纯日期部分(去掉时间),避免时间干扰匹配 var targetDate = date.Date; var query = await (from e in _dbContext.Employees join att in _dbContext.Attendances on e.Id equals att.EmployeeId into empAttGroup // 筛选该员工在指定日期的考勤记录,没有则返回null from empAtt in empAttGroup.Where(a => a.AttendanceDate.Date == targetDate).DefaultIfEmpty() // 没有匹配到考勤记录,即为缺勤 where empAtt == null select new AbsentReportsViewModel { JobId = e.JobId, EmpReportName = e.NameMM, DeptId = e.DeptId, RankId = e.CurrentRankId, DeptReportName = e.Department.DeptName, RankReportName = e.Rank.RankName, BarCode = e.Barcode, EmpReportId = e.Id, }).ToListAsync(); return query; }
关键修改点
- 日期匹配逻辑:用
a.AttendanceDate.Date == targetDate替代直接相等,确保只比较日期部分,避免考勤记录中时间(如签到时间)导致的匹配失败 - 左连接判断:将
where eattt.AttendanceDate == null改为where empAtt == null,因为左连接无匹配时,empAtt整个对象为null,直接访问属性会引发空引用异常 - 参数处理:提前提取
date.Date作为目标日期,统一后续比较逻辑
额外优化建议
如果你的数据库中AttendanceDate存储的是带时间的DateTime,也可以使用EF Core的数据库函数来优化查询(避免客户端评估):
// 使用EF.Functions.TruncateTime来在数据库层面截断时间 from empAtt in empAttGroup.Where(a => EF.Functions.TruncateTime(a.AttendanceDate) == targetDate).DefaultIfEmpty()
内容的提问来源于stack exchange,提问作者Lune lune
相关产品推荐
相关产品推荐

