You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Linq将C#透视表数据转换为ViewModel并默认值为0?

问题

现有业务场景:数据库中的值表存储了不同职位层级(JobLevel)、性别(Gender)、颜色(Color)的员工数量数据,需按JobLevel进行透视后在DataGridControl中展示,且允许用户修改数值。需要先将数据库返回的EmployeeGroupValue数据转换为指定的EmployeeGroupValueViewModel对象,无对应数据时默认值为0。

枚举定义

public enum JobLevel
{
    Top,
    Mid,
    Low
}

public enum Color
{
    Red,
    Blue,
    Green
}

public enum Gender
{
    Female,
    Male,
    Other
}

值实体类

public class EmployeeGroupValue
{
    [Key, Column(Order = 0)]
    [Required]
    public JobLevel JobLevel { get;set; }
    [Key, Column(Order = 1)]
    [Required]
    public Gender Gender { get;set; }
    [Key, Column(Order = 2)]
    [Required]
    public Color Color { get;set; }
    [Required]
    public int Value { get;set; }
}

示例数据

IdJobLevelGenderColorValue
1TopMaleRed10
2TopOtherRed5
3TopFemaleBlue20
4MidOtherBlue5
5MidFemaleGreen50
6LowMaleGreen5
7LowOtherRed7
8LowFemaleGreen12

目标DataGrid展示样式

表头行1

JobLevelFemaleMaleOther

表头行2与数据行

xxxxxxxxxxxxRBGRBGRBG
Top02001000500
Mid0050000050
Low0012005700

指定ViewModel

public class EmployeeGroupValueViewModel
{
     public string JobLevel { get;set; }
     public int FemaleRed { get;set; }
     public int FemaleBlue { get;set; }
     public int FemaleGreen { get;set; }
     public int MaleRed { get;set; }
     public int MaleBlue { get;set; }
     public int MaleGreen { get;set; }
     public int OtherRed { get;set; }
     public int OtherBlue { get;set; }
     public int OtherGreen { get;set; }
}

请问如何使用Linq实现上述数据转换,且无对应数据库行时默认值为0?


解决方案

可以通过Linq分组结合字典快速查找的方式实现,具体代码如下:

// 假设dbValues是从数据库查询得到的EmployeeGroupValue集合
var dbValues = new List<EmployeeGroupValue>(); // 替换为实际数据库查询结果

// 将原始数据转换为字典,键为(JobLevel, Gender, Color)的元组,便于快速取值
var valueLookup = dbValues.ToDictionary(
    item => (item.JobLevel, item.Gender, item.Color),
    item => item.Value
);

// 生成所有职位层级对应的ViewModel,确保无数据时默认值为0
var viewModels = Enum.GetValues<JobLevel>()
    .Select(level => new EmployeeGroupValueViewModel
    {
        JobLevel = level.ToString(),
        // 女性各颜色对应值
        FemaleRed = valueLookup.TryGetValue((level, Gender.Female, Color.Red), out int val) ? val : 0,
        FemaleBlue = valueLookup.TryGetValue((level, Gender.Female, Color.Blue), out val) ? val : 0,
        FemaleGreen = valueLookup.TryGetValue((level, Gender.Female, Color.Green), out val) ? val : 0,
        // 男性各颜色对应值
        MaleRed = valueLookup.TryGetValue((level, Gender.Male, Color.Red), out val) ? val : 0,
        MaleBlue = valueLookup.TryGetValue((level, Gender.Male, Color.Blue), out val) ? val : 0,
        MaleGreen = valueLookup.TryGetValue((level, Gender.Male, Color.Green), out val) ? val : 0,
        // 其他性别各颜色对应值
        OtherRed = valueLookup.TryGetValue((level, Gender.Other, Color.Red), out val) ? val : 0,
        OtherBlue = valueLookup.TryGetValue((level, Gender.Other, Color.Blue), out val) ? val : 0,
        OtherGreen = valueLookup.TryGetValue((level, Gender.Other, Color.Green), out val) ? val : 0
    })
    .ToList();

代码说明

  1. 字典转换:用ToDictionary将原始数据转为元组键的字典,实现O(1)时间复杂度的查找,提升效率;
  2. 遍历所有层级:通过Enum.GetValues<JobLevel>()遍历所有职位层级,确保即使数据库中没有对应层级的数据,也能生成默认值为0的行;
  3. 默认值处理:每个ViewModel属性通过TryGetValue判断是否存在对应数据,不存在则赋值0,完全符合需求。

内容的提问来源于stack exchange,提问作者Donald N. Mafa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 02:35:26