.NET Core 5.0 Linq GroupBy查询报错及分组查询实现需求
问题解决:Linq GroupBy在EF Core 5.0中的类型不匹配错误
错误原因
你在EF Core查询的投影阶段(构造ReservationViewModel时),对Service字段的子查询先调用了.ToList(),紧接着执行.GroupBy()。此时EF Core会尝试将GroupBy操作翻译成数据库查询,但.ToList()已经将子查询结果转换成了内存集合List<AdminReservationviewModel>,而EF的GroupBy方法要求参数是IQueryable<T>类型,因此抛出类型不匹配的错误。
解决方案
将分组操作放到内存中执行,先把所需的基础数据加载到内存,再进行分组和ViewModel构造,避免EF尝试翻译内存集合上的查询操作。
修改后的Controller代码
// 1. 加载主预订数据到内存 var baseReservations = (from reservation in c_.Reservations join times in c_.Times on reservation.TimeId equals times.TimeId join users in c_.Users on reservation.EmployerId equals users.UserId orderby reservation.Date select new { reservation.MeetingId, users.UserName, reservation.Date, times.TimeName, reservation.ToplamSure, reservation.ToplamTutar }).ToList(); // 2. 加载所有关联的服务数据到内存 var relatedServices = (from m in c_.MultiReservations join s in c_.Services on m.ServiceId equals s.ServiceId select new { m.MeetingId, m.ServiceId, s.Operation }).ToList(); // 3. 构造最终ViewModel并在内存中分组 var t = baseReservations.Select(res => new ReservationViewModel { MeetingId = res.MeetingId, UserName = res.UserName, Date = res.Date, Time = res.TimeName, ToplamSure = res.ToplamSure, ToplamTutar = res.ToplamTutar, Service = relatedServices .Where(s => s.MeetingId == res.MeetingId) .Select(s => new AdminReservationviewModel { ServiceId = s.ServiceId, Operations = s.Operation }) .GroupBy(s => s.ServiceId) .ToList() }).ToList();
可选优化:合并同ServiceId的操作名称
如果同一个ServiceId对应多个操作,你可以用string.Join合并操作名称,修改Service字段的构造代码:
Service = relatedServices .Where(s => s.MeetingId == res.MeetingId) .GroupBy(s => s.ServiceId) .Select(grp => new AdminReservationviewModel { ServiceId = grp.Key, Operations = string.Join("、", grp.Select(s => s.Operation)) }) .GroupBy(s => s.ServiceId) .ToList()
关键说明
- 先调用
.ToList()将EF查询结果加载到内存,后续的GroupBy、Select等操作就会在内存中执行,避免EF尝试翻译不支持的操作组合。 - 这种方式会两次查询数据库(主预订数据和关联服务数据),如果数据量不大,性能影响可以忽略;如果数据量较大,可考虑使用Include/ThenInclude预加载关联数据,但仍需注意在内存中处理分组。
内容的提问来源于stack exchange,提问作者Nesibe Cetin
相关产品推荐
相关产品推荐

