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

Linq GroupBy含可空属性:如何跳过子列表中的空对象

问题分析与解决

我有一张包含两个引用类ID的Class1表,希望按Class2的两个属性分组,仅将非空的Class3添加到子列表。尝试两种Linq写法后仍无法跳过空项,列表中仍会出现空对象。

原始代码

var groupData = await _context.Class1
            .Where(ct => ct.Id == Id                
            && ct.C2 != null )
            .Select(h => new { h.Class2.F1, h.Class2.F2,  h.Class3 }
            ).ToListAsync();
        var result = groupData.GroupBy(g => new { g.F1, g.F2 }).Select(h => new MyResult
        {
            F1 = h.Key.F1,
            F2 = h.Key.F2,           
            F4List = h.Select(x =>new MyModel
            {
                C5F1 = x.Class3.F1,
                C5F2 = x.Class3.F2,
                C5F3 = x.Class3.F3,                
            }).ToList()
            
        }).ToList();

修改后代码

var groupData = await _context.Class1
            .Where(ct => ct.Id == Id                
            && ct.C2 != null )
            .Select(h => new { h.Class2.F1, h.Class2.F2,  h.Class3 }
            ).ToListAsync();
        var result = groupData.GroupBy(g => new { g.F1, g.F2 }).Select(h => new MyResult
        {
            F1 = h.Key.F1,
            F2 = h.Key.F2,           
            F4List = h.Select(x => x.Class3 != null ? new MyModel
            {
                C5F1 = x.Class3.F1,
                C5F2 = x.Class3.F2,
                C5F3 = x.Class3.F3,                
            }: null).ToList()
            
        }).ToList();

Class1结构

public class Class1
{
    int Id;
    int class2ID;
    int? class3ID;

    virtual Class2 Class2;
    virtual Class3 Class3;
}

问题原因与解决方法

问题所在

  1. 原始代码:未过滤Class3为空的项,直接创建MyModel,当x.Class3为空时会触发空引用异常,即使未抛出异常,也会生成无效的MyModel对象。
  2. 修改后代码:虽然判断了x.Class3 != null,但空值场景返回null并直接加入列表,导致F4List中包含null元素,而非跳过这些项。

解决办法

生成F4List时,先通过Where过滤掉Class3为空的项,再执行Select创建MyModel:

var groupData = await _context.Class1
    .Where(ct => ct.Id == Id && ct.Class2 != null)
    .Select(h => new { h.Class2.F1, h.Class2.F2, h.Class3 })
    .ToListAsync();

var result = groupData
    .GroupBy(g => new { g.F1, g.F2 })
    .Select(h => new MyResult
    {
        F1 = h.Key.F1,
        F2 = h.Key.F2,
        F4List = h.Where(x => x.Class3 != null)
                  .Select(x => new MyModel
                  {
                      C5F1 = x.Class3.F1,
                      C5F2 = x.Class3.F2,
                      C5F3 = x.Class3.F3,
                  }).ToList()
    }).ToList();

优化建议

可将过滤逻辑提前到EF查询阶段,减少内存处理的数据量,提升性能:

var result = await _context.Class1
    .Where(ct => ct.Id == Id && ct.Class2 != null && ct.Class3 != null)
    .GroupBy(ct => new { ct.Class2.F1, ct.Class2.F2 })
    .Select(g => new MyResult
    {
        F1 = g.Key.F1,
        F2 = g.Key.F2,
        F4List = g.Select(ct => new MyModel
        {
            C5F1 = ct.Class3.F1,
            C5F2 = ct.Class3.F2,
            C5F3 = ct.Class3.F3,
        }).ToList()
    }).ToListAsync();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 04:18:14