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

如何用LINQ按日期分组生成含客户与嵌套记录的报表行列表?

按日期、客户分组生成报表的实现方案

核心思路

通过LINQ对Record列表进行两次分组:先按ImportTimestamp的日期部分分组,再在每个日期组内按Customer分组,最终映射到ReportRow列表供视图渲染。

步骤1:优化数据查询(避免N+1问题)

首先确保从数据库查询时提前加载Customer关联数据,避免Entity Framework延迟加载导致的性能问题:

// 替换原Db.GetRecords方法,确保包含Customer关联
IEnumerable<Record> Records = Db.Records
    .Where(r => r.ImportTimestamp >= StartDate && r.ImportTimestamp <= EndDate)
    .Include(r => r.Customer) // 预加载Customer,避免N+1查询
    .ToList();

步骤2:分组生成ReportRow列表

使用LINQ分组并转换为视图模型需要的结构:

// 生成报表行数据
var reportRows = Records
    // 第一层:按日期分组(忽略时间部分)
    .GroupBy(r => r.ImportTimestamp.Date)
    .Select(dateGroup => new ReportRow
    {
        ImportDate = dateGroup.Key,
        // 第二层:在当前日期组内按Customer分组
        Customers = dateGroup
            .GroupBy(r => r.Customer)
            .Select(customerGroup => 
            {
                // 给Customer的Records属性赋值当前组的记录
                customerGroup.Key.Records = customerGroup.ToList();
                return customerGroup.Key;
            })
            .OrderBy(c => c.Name) // 可选:按客户名称排序
    })
    .OrderBy(row => row.ImportDate) // 按日期升序排列
    .ToList();

// 赋值到视图模型
ViewModel.Rows = reportRows;

步骤3:视图层渲染示例(以Razor为例)

遍历ReportRow列表,按预期格式展示:

@foreach (var row in Model.Rows)
{
    <h3>@row.ImportDate.ToString("dd/MM/yyyy")</h3>
    <ul>
        @foreach (var customer in row.Customers)
        {
            <li>@customer.Name
                <ul>
                    @foreach (var record in customer.Records)
                    {
                        <li>@record.OrderRef (记录ID: @record.ID)</li>
                    }
                </ul>
            </li>
        }
    </ul>
}

可选优化:使用DTO避免修改原实体

如果不想修改Customer实体的Records属性(防止影响其他业务逻辑),可以创建专门的DTO类:

// 定义客户DTO
public class CustomerReportDTO
{
    public string Name { get; set; } = default!;
    public IEnumerable<Record> Records { get; set; } = default!;
}

// 修改ReportRow的Customers类型
public class ReportRow
{
     public DateTime ImportDate { get; set; }
     public IEnumerable<CustomerReportDTO> Customers { get; set; }         
}

然后调整分组逻辑:

Customers = dateGroup
    .GroupBy(r => r.Customer)
    .Select(customerGroup => new CustomerReportDTO
    {
        Name = customerGroup.Key.Name,
        Records = customerGroup.ToList()
    })
    .OrderBy(c => c.Name)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 16:50:31