如何使用LINQ填充含子集合的ProjectApprovalViewModel?
解决方案:用LINQ分组转换扁平数据至嵌套ViewModel
没问题,这事儿用LINQ的GroupBy就能完美解决,我给你拆解一下实现步骤和代码示例:
1. 先明确相关结构(方便对照)
首先,假设你的扁平查询结果对应如下实体类(如果是EF查询,也可以直接用数据库实体或匿名类型,这里用强类型示例更清晰):
// 扁平数据的实体/DTO public class FlatApprovalRecord { public int ProjectApprovalHeaderId { get; set; } public string StepName { get; set; } public string Status { get; set; } }
你的ViewModel定义(和你给出的完全一致):
public class ProjectApprovalHeaderVM { public int ProjectApprovalHeaderId { get; set; } public List<ProjectApprovalStepsVM> ProjectApprovalHistorySteps { get; set; } } public class ProjectApprovalStepsVM { public string StepName { get; set; } public string Status { get; set; } }
2. 核心LINQ转换代码
不管是内存中的集合,还是EF Core从数据库直接查询的结果,都可以用下面的代码完成转换:
// 假设flatApprovalRecords是你的扁平查询结果集合(IEnumerable<FlatApprovalRecord>) var headerViewModels = flatApprovalRecords // 按ProjectApprovalHeaderId分组,把同ID的步骤归为一组 .GroupBy(record => record.ProjectApprovalHeaderId) // 遍历每个分组,转换为目标ViewModel .Select(group => new ProjectApprovalHeaderVM { ProjectApprovalHeaderId = group.Key, // 分组键就是当前组的HeaderId // 将分组内的扁平记录转换为StepsVM子集合 ProjectApprovalHistorySteps = group.Select(stepRecord => new ProjectApprovalStepsVM { StepName = stepRecord.StepName, Status = stepRecord.Status }).ToList() }) .ToList();
3. 关键逻辑解释
GroupBy(record => record.ProjectApprovalHeaderId):把所有扁平数据按审批头ID聚合,每个分组包含同一个审批头的所有步骤记录。- 分组后的
group.Key就是当前组的审批头ID,直接赋值给ViewModel的对应属性。 - 对分组内的每条记录,映射为
ProjectApprovalStepsVM对象,最后通过ToList()转换为子集合。
额外注意事项
如果是在EF Core中直接执行数据库查询,这种GroupBy+投影的写法是可以被EF Core解析为SQL的(只要分组键是简单类型),不需要先把数据拉到内存。如果遇到EF Core无法解析的特殊场景,再加上.AsEnumerable()切换到内存中处理即可。
内容的提问来源于stack exchange,提问作者TrevorGoodchild
相关产品推荐
相关产品推荐

