EF查询中HasValue条件导致结果异常的解决方案
问题根因
原单Where写法的逻辑错误出在可选筛选条件的判断上:用request.DepartmentId.HasValue && 匹配值的写法,等价于要求「必须传入DepartmentId且值匹配」才会返回结果,当DepartmentId/RoomType为空时,整个判断条件直接返回false,自然无法返回预期结果。
拆分多个Where的版本逻辑是正确的:每个可选筛选遵循参数为空则跳过筛选,参数有值才匹配对应字段的规则,判断逻辑为!request.xxx.HasValue || 匹配值。
单Where正确实现
多个连续调用的Where本质是条件的与(AND)关系,直接把所有条件按正确逻辑用&&拼接在单个Where中即可,EF Core会自动生成和拆分Where完全一致的SQL,不会有性能差异:
public async Task<Response> Handle(GetAvailableRoomsQuery request, CancellationToken cancellationToken) { // 查询指定时间段内所有已安排的课程活动 var classActivities = await _sender.Send( new GetClassActivitiesQuery { From = request.From, To = request.To }, cancellationToken); // 提取时间段内已被占用的房间ID集合 var unavailableRoomIds = new HashSet<int>(classActivities.Select(e => e.RoomId)); return await _context.Rooms .Where(room => // 基础必选条件:排除时间段内已被占用的房间 !unavailableRoomIds.Contains(room.Id) // 可选条件:未传部门ID时不做筛选,传值则匹配对应部门 && (!request.DepartmentId.HasValue || request.DepartmentId.Value == room.DepartmentId) // 可选条件:未传房间类型时不做筛选,传值则匹配对应房型 && (!request.RoomType.HasValue || request.RoomType.Value == room.Type) ) .ProjectTo<RoomDto>(_mapper.ConfigurationProvider) .ToListAsync(cancellationToken); }
补充说明
- EF Core在翻译这类可空参数的判断时会做自动优化:如果参数
HasValue为false,最终生成的SQL中不会包含对应字段的筛选条件,完全符合可选筛选的需求 - 注意给每个可选条件的判断加上括号,避免逻辑运算符优先级导致判断顺序出错
内容的提问来源于stack exchange,提问作者nop
相关产品推荐
相关产品推荐

