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

C#基于EF编写LINQ实现分类供应商动态列分组透视统计

EF Core 动态透视表实现(输出可直接绑定DataTable)

实体映射(对应三张业务表)

首先确认EF实体映射和表结构匹配,核心实体定义如下:

public class Vendor
{
    public int VendorId { get; set; }
    public string VendorName { get; set; }
}

public class Category
{
    public int CategoryId { get; set; }
    public string CategoryName { get; set; }
}

public class Product
{
    public int ProductId { get; set; }
    public int VendorId { get; set; }
    public int CategoryId { get; set; }
    // 导航属性,提前配置好EF关联映射
    public Vendor Vendor { get; set; }
    public Category Category { get; set; }
}

实现逻辑

  • 聚合逻辑下推到数据库执行:三表关联+分组计数的操作全部生成SQL执行,只返回聚合后的轻量结果,避免加载全量商品明细到内存
  • 动态列自动生成:从聚合结果中提取全量不重复供应商作为列,后续新增供应商无需修改代码会自动生成对应列
  • 动态构建DataTable:固定分类维度列+动态供应商列+总计列,逐行填充计数结果,最终输出的DataTable可直接绑定到数据控件

完整代码

public async Task<DataTable> GetProductPivotTableAsync()
{
    using var db = new YourAppDbContext();
    
    // 数据库侧执行聚合,返回分类-供应商维度的商品计数
    var aggResult = await (
        from p in db.Products
        join c in db.Categories on p.CategoryId equals c.CategoryId
        join v in db.Vendors on p.VendorId equals v.VendorId
        group p by new { c.CategoryId, c.CategoryName, v.VendorId, v.VendorName } into g
        select new 
        {
            g.Key.CategoryId,
            g.Key.CategoryName,
            g.Key.VendorId,
            g.Key.VendorName,
            Count = g.Count()
        }
    ).AsNoTracking().ToListAsync();

    // 提取所有供应商作为动态列,可按需调整排序规则
    var vendorColumns = aggResult
        .Select(x => new { x.VendorId, x.VendorName })
        .Distinct()
        .OrderBy(v => v.VendorName)
        .ToList();

    // 初始化DataTable结构
    var pivotTable = new DataTable();
    pivotTable.Columns.Add("CategoryId", typeof(int));
    pivotTable.Columns.Add("分类名称", typeof(string));
    foreach (var vendor in vendorColumns)
    {
        pivotTable.Columns.Add(vendor.VendorName, typeof(int));
    }
    pivotTable.Columns.Add("总计", typeof(int));

    // 按分类分组填充行数据
    foreach (var catGroup in aggResult.GroupBy(x => new { x.CategoryId, x.CategoryName }))
    {
        var row = pivotTable.NewRow();
        row["CategoryId"] = catGroup.Key.CategoryId;
        row["分类名称"] = catGroup.Key.CategoryName;
        int totalCount = 0;
        foreach (var vendor in vendorColumns)
        {
            var currentCount = catGroup.FirstOrDefault(x => x.VendorId == vendor.VendorId)?.Count ?? 0;
            row[vendor.VendorName] = currentCount;
            totalCount += currentCount;
        }
        row["总计"] = totalCount;
        pivotTable.Rows.Add(row);
    }

    return pivotTable;
}

优化说明

  • 加了AsNoTracking取消变更追踪,进一步提升查询性能
  • 供应商对应计数为空时默认填0,避免出现DBNull导致绑定控件报错
  • 如果需要过滤无效供应商、已下架分类,直接在聚合查询部分加Where条件即可,后续逻辑无需调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:57:19