LINQ多对多左连接后按Complaint分组及用户归集实现方法
分组Complaint并关联分配的ApplicationUser
1. 先明确实体与ViewModel结构
假设你的实体及ViewModel简化结构如下:
public class Complaint { public int Id { get; set; } public string Title { get; set; } // 其他业务属性 } public class ApplicationUser { public string Id { get; set; } public string UserName { get; set; } // 其他用户属性 } public class AsignComplaintToUsers { public int ComplaintId { get; set; } public string UserId { get; set; } public Complaint Complaint { get; set; } public ApplicationUser User { get; set; } } // 用于展示的ViewModel public class ComplaintViewModel { public int ComplaintId { get; set; } public string ComplaintTitle { get; set; } public List<ApplicationUser> AssignedUsers { get; set; } = new List<ApplicationUser>(); // 其他需要展示的属性 }
2. 分组查询与ViewModel赋值
方式一:基于已有左连接数据分组
如果已经通过左连接获取了包含Complaint、关联表、用户的基础集合,可以直接在内存中分组转换:
// 假设这是你已获取的左连接基础数据 var leftJoinData = _context.Complaints .GroupJoin(_context.AsignComplaintToUsers, c => c.Id, ac => ac.ComplaintId, (c, acs) => new { Complaint = c, Assignments = acs.DefaultIfEmpty() }) .SelectMany( x => x.Assignments, (x, ac) => new { x.Complaint, ac, User = ac != null ? ac.User : null }) .ToList(); // 分组并转换为ViewModel var complaintViewModels = leftJoinData .GroupBy(item => item.Complaint.Id) .Select(group => new ComplaintViewModel { ComplaintId = group.Key, ComplaintTitle = group.First().Complaint.Title, AssignedUsers = group.Where(g => g.User != null).Select(g => g.User).ToList() }) .ToList();
方式二:直接在EF Core查询中完成分组(更高效)
如果还未执行左连接,建议直接在数据库层面完成分组关联,减少内存数据处理压力:
var complaintViewModels = _context.Complaints .Select(c => new ComplaintViewModel { ComplaintId = c.Id, ComplaintTitle = c.Title, AssignedUsers = _context.AsignComplaintToUsers .Where(ac => ac.ComplaintId == c.Id) .Select(ac => ac.User) .ToList() }) .ToList();
3. 手动遍历分组结果赋值
如果需要逐行处理分组数据而不是直接用Select转换:
var groupedData = leftJoinData.GroupBy(item => item.Complaint.Id); var complaintViewModels = new List<ComplaintViewModel>(); foreach (var group in groupedData) { var targetComplaint = group.First().Complaint; var vm = new ComplaintViewModel { ComplaintId = group.Key, ComplaintTitle = targetComplaint.Title }; // 遍历组内用户,添加到ViewModel集合 foreach (var item in group) { if (item.User != null) { vm.AssignedUsers.Add(item.User); } } complaintViewModels.Add(vm); }
关键注意点
- 如果是左连接查询,必须处理
User为null的情况,避免空引用异常 - 优先选择在EF Core查询中完成分组关联,数据量较大时性能优势明显
- 若已配置实体导航属性(比如Complaint下的
AssignedLinks导航到AsignComplaintToUsers),可以进一步简化查询:// 前提:Complaint实体已配置导航属性 public ICollection<AsignComplaintToUsers> AssignedLinks { get; set; } var viewModel = _context.Complaints .Include(c => c.AssignedLinks) .ThenInclude(ac => ac.User) .Select(c => new ComplaintViewModel { ComplaintId = c.Id, ComplaintTitle = c.Title, AssignedUsers = c.AssignedLinks.Select(ac => ac.User).ToList() }) .ToList();
内容的提问来源于stack exchange,提问作者Fawad
相关产品推荐
相关产品推荐

