【问题标题】:linq selectmany flatten multiple levelslinq selectman 展平多个级别
【发布时间】:2025-11-23 19:15:01
【问题描述】:

我有以下关系(例如)

A 包含一个或多个 B

每个 B 包含一个或多个 C 和 D

我想使用 SelectMany 以及一些搜索条件来展平所有内容并获得 A,B,C 和 D's 。这就是我所拥有的。

context.A.Where(a => (string.IsNullOrEmpty(name) || a.Name.Contains(name)))
    .SelectMany(ab =>ab.b.Where(n=>n.bname.Contains(name) || string.IsNullOrEmpty(name)),     
    (aa, bb) => new { aa, bb })   //gets all a's and b's
    .SelectMany(bc => bb.c.Where(w => w.KEYWORD.Contains(Keyword) || string.IsNullOrEmpty(Keyword)),
    (bc,words) => new {bc,kwords})  //gets all b's and c's

我做的对吗?如果是这样,那么如何将 B 与所有 D 添加到上述表达式中?

【问题讨论】:

  • 我建议你在这种情况下使用查询语法。

标签: c# linq


【解决方案1】:

使用 Lambda 语法进行数据选择:

var flatData = context.A.SelectMany(a => a.B.SelectMany(b => b.Select(new {a,b,c = b.C,d = b.D})

更进一步,在应用 Where 子句之前应进行以下检查,因为它们检查提供的常量输入,namekeyword

  1. string.IsNullOrEmpty(name)
  2. string.IsNullOrEmpty(keyword)

剩下的检查很简单:

if(!string.IsNullOrEmpty(name))
    flatData  = flatData.Where(data => data.a.Name.Contains(name))
                        .Where(data => data.b.Name.Contains(name));

if(!string.IsNullOrEmpty(keyword))
   flatData  = flatData.Where(data => data.c.Keyword.Contains(keyword));

要点:

  • flatData 上面有一个级联过滤器,首先在a.Name, b.Name and c.Keyword

【讨论】:

    【解决方案2】:

    同意 Ivan 的建议,您可以像这样将这 3 层深度结构展平:

    var query = (from a in A
                 from b in (List<dynamic>)a.b
                 from c in (List<dynamic>)b.c
                 from d in (List<dynamic>)b.d
                 select new { a, b, c, d });
    
    if (!string.IsNullOrEmpty(name))
    {
        query = query.Where(record => record.b.bname.Contains(name));
    }
    
    if (!string.IsNullOrEmpty(keyword))
    {
        query = query.Where(record => record.c.keyword.Contains(keyword));
    }
    
    var result = query.ToList();
    

    您还可以在顶部的查询中添加 where 子句,但看到您正在检查是否有任何有效输入,我会将其放在后面

    使用此示例数据对其进行了测试:

    List<dynamic> A = new List<dynamic>
    {
        new { b = new List<dynamic> { new { bname = "a", c = new List<dynamic> { new { keyword = "b" } }, d = new List<dynamic> { 1, 2, 3 } } } },
        new { b = new List<dynamic> { new { bname = "a", c = new List<dynamic> { new { keyword = "d" } }, d = new List<dynamic> { 1, 2, 3 } } } }
    };
    
    string name = "a";
    string keyword = "b";
    

    【讨论】:

    • 我的级别不是 4 级深...A->B->C 和 D 那么我应该如何重组您的查询呢?
    • example.. Team(A) 由 TeamMembers(B) 组成。每个 TeamMember(B) 可以拥有多种技能(C) 并与多个项目相关联(D)
    • 您的查询似乎比使用 lambda 简单得多。让我试试这个谢谢!
    • @cableload - 让我知道它是怎么回事 :) 顺便说一句,下次如果你解释结构并提供一些示例数据(如测试数据)会更简单并吸引更多人来帮助你我在问题末尾添加了)
    • 我有另一个快速的问题..如果我有另一个表调用 V,其结构是 (id,value) 并且与关系 d.id 相关,我将如何将其添加到上述查询中? (显然我需要加入D和V)