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

如何在LINQ Core中实现行转列与逆透视?附SQL参考代码

在LINQ Core中实现UNPIVOT(逆透视)功能

好问题!LINQ本身并没有像SQL里那样提供直接的UNPIVOT内置方法,但我们可以通过灵活的方式实现完全相同的逆透视效果,核心思路是利用SelectMany将每个“宽行”拆解为多个“窄行”。

先明确数据模型

假设你的透视后数据(对应SQL里的#temp表)对应的C#模型是这样的:

public class PivotedTranslation
{
    public string ResourceName { get; set; }
    public string ENText { get; set; }
    public string FRText { get; set; }
    public string ZHText { get; set; }
    public string DEText { get; set; }
    public string ITText { get; set; }
    public string JAText { get; set; }
    public string PTText { get; set; }
    public string PTBRText { get; set; } // 对应SQL中的[PT-BRText]
    public string RUText { get; set; }
    public string ESText { get; set; }
    public string SVText { get; set; }
}

而你想要的逆透视后的数据模型(对应SQL里的UnpivotTranslation结果)是:

public class UnpivotedTranslation
{
    public Guid Id { get; set; }
    public string ResourceName { get; set; }
    public string LanguageID { get; set; }
    public string Translation { get; set; }
}

实现逆透视的LINQ查询

使用SelectMany方法,将每个PivotedTranslation对象拆分为多个UnpivotedTranslation对象,每个对象对应一个语言列:

// 假设pivotedData是你的透视后数据源(可以是EF Core的DbSet,或者内存集合)
var unpivotedData = pivotedData.SelectMany(p => new[]
{
    new UnpivotedTranslation { Id = Guid.NewGuid(), ResourceName = p.ResourceName, LanguageID = "ENText", Translation = p.ENText },
    new UnpivotedTranslation { Id = Guid.NewGuid(), ResourceName = p.ResourceName, LanguageID = "FRText", Translation = p.FRText },
    new UnpivotedTranslation { Id = Guid.NewGuid(), ResourceName = p.ResourceName, LanguageID = "ZHText", Translation = p.ZHText },
    new UnpivotedTranslation { Id = Guid.NewGuid(), ResourceName = p.ResourceName, LanguageID = "DEText", Translation = p.DEText },
    new UnpivotedTranslation { Id = Guid.NewGuid(), ResourceName = p.ResourceName, LanguageID = "ITText", Translation = p.ITText },
    new UnpivotedTranslation { Id = Guid.NewGuid(), ResourceName = p.ResourceName, LanguageID = "JAText", Translation = p.JAText },
    new UnpivotedTranslation { Id = Guid.NewGuid(), ResourceName = p.ResourceName, LanguageID = "PTText", Translation = p.PTText },
    new UnpivotedTranslation { Id = Guid.NewGuid(), ResourceName = p.ResourceName, LanguageID = "PT-BRText", Translation = p.PTBRText },
    new UnpivotedTranslation { Id = Guid.NewGuid(), ResourceName = p.ResourceName, LanguageID = "RUText", Translation = p.RUText },
    new UnpivotedTranslation { Id = Guid.NewGuid(), ResourceName = p.ResourceName, LanguageID = "ESText", Translation = p.ESText },
    new UnpivotedTranslation { Id = Guid.NewGuid(), ResourceName = p.ResourceName, LanguageID = "SVText", Translation = p.SVText }
})
// 可选:过滤掉空的翻译值,和你SQL里MAX聚合后过滤空值的逻辑对应
.Where(ut => !string.IsNullOrEmpty(ut.Translation))
.OrderBy(ut => ut.ResourceName);

关键说明

  • SelectMany是实现逆透视的核心:它把单个源对象“展开”为多个目标对象,完美对应SQLUNPIVOT将列转为行的逻辑。
  • 如果你的数据源是EF Core的DbSet,这个LINQ查询会被EF Core自动转换为等价的SQL语句执行,性能和你手写的UNPIVOT SQL相近。
  • 要是你想避免硬编码列名(比如语言列可能动态变化),可以用反射遍历PivotedTranslation的属性,但注意反射方式在EF Core中无法被转换为SQL,只适合内存中的数据处理。

内容的提问来源于stack exchange,提问作者Shardul

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:37:23