【问题标题】:Datatable and LINQ Parent / Child relationship数据表和 LINQ 父/子关系
【发布时间】:2012-06-24 11:30:07
【问题描述】:

得到带有 ID、parentId、描述的数据表。它是一个关系表结构。

我希望能够将参数传递给一个函数,该函数是树视图中项目的当前选定 ID。我想返回一个包含所有相关子行的数据表,关系的顶部是 parentId 为空......等等

我想做这个 LINQ

欢迎任何帮助。

enter code here var kids = ( from p in dt.AsEnumerable()
                     where p.Field<Int32?>( "ParentId" ) == parentId
                     select new
                     {
                         parent = p,
                         child = from c in dt.AsEnumerable()
                                 where c.Field<Int32?>( "ParentId" ) == p.Field<Int32>( "Id" )
                                 select new
                                 {
                                     child = c
                                 }
                     } ).ToList();

以下是我正在使用的数据,我无法让它按预期工作。也许我们谈论的不是相同的最终结果,或者我错过了一些可怕的东西。

这是我拥有的代码,当我为 parentId 传递一个 57 的值时,我会在子项中返回 2 行。

QuotationItemId=58 和 71

我也希望得到 QuotationItemId 59, 60, 55 ,56, 61

        var lookup = dt.AsEnumerable().ToLookup( p => p.Field<int?>( "ParentId" ) );
        var children = lookup[parentId].ToList();

【问题讨论】:

    标签: c# linq datatable


    【解决方案1】:

    这是你可以做的:

    var lookup =
        dt
            .AsEnumerable()
            .ToLookup(p => p.Field<int?>("ParentId"));
    

    现在,如果您想要根元素,请执行以下操作:

    var roots = lookup[null];
    

    如果你想要孩子,给定parentId,你可以这样做:

    var children = lookup[parentId];
    

    简单吧?


    这里有一些基于您的编辑的代码。

    我使用匿名类型定义了我的项目列表:

    var items = new []
    {
        new { QuotationItemId = 54, ParentId = (int?)null, Description = "0000", },
        new { QuotationItemId = 55, ParentId = (int?)60, Description = "Product 55", },
        new { QuotationItemId = 56, ParentId = (int?)60, Description = "Product 56", },
        new { QuotationItemId = 57, ParentId = (int?)54, Description = "Category 57", },
        new { QuotationItemId = 58, ParentId = (int?)57, Description = "Sub Category 58", },
        new { QuotationItemId = 59, ParentId = (int?)58, Description = "Product 59", },
        new { QuotationItemId = 60, ParentId = (int?)58, Description = "Standard Ratel", },
        new { QuotationItemId = 61, ParentId = (int?)60, Description = "Product 61", },
        new { QuotationItemId = 62, ParentId = (int?)null, Description = "Stage 62", },
        new { QuotationItemId = 63, ParentId = (int?)62, Description = "Product 63", },
        new { QuotationItemId = 64, ParentId = (int?)62, Description = "Product 64", },
        new { QuotationItemId = 65, ParentId = (int?)62, Description = "Category 65", },
        new { QuotationItemId = 66, ParentId = (int?)65, Description = "Sub Category66", },
        new { QuotationItemId = 67, ParentId = (int?)66, Description = "Product 67", },
        new { QuotationItemId = 68, ParentId = (int?)66, Description = "Standard Rate 2", },
        new { QuotationItemId = 69, ParentId = (int?)68, Description = "Product 69", },
        new { QuotationItemId = 71, ParentId = (int?)57, Description = "Sub Category 71", },
        new { QuotationItemId = 72, ParentId = (int?)54, Description = "Category 72", },
        new { QuotationItemId = 73, ParentId = (int?)72, Description = "Sub Category73", },
        new { QuotationItemId = 74, ParentId = (int?)73, Description = "Product 74", },
        new { QuotationItemId = 75, ParentId = (int?)73, Description = "Product 75", },
        new { QuotationItemId = 77, ParentId = (int?)null, Description = "qqqqqqqqqq", },
        new { QuotationItemId = 78, ParentId = (int?)null, Description = "zzzzzz", },
        new { QuotationItemId = 79, ParentId = (int?)null, Description = "Test 12345", },
        new { QuotationItemId = 80, ParentId = (int?)null, Description = "456", },
        new { QuotationItemId = 81, ParentId = (int?)null, Description = "tttt", },
        new { QuotationItemId = 82, ParentId = (int?)null, Description = "reddddy777", },
        new { QuotationItemId = 83, ParentId = (int?)null, Description = "bbbbbbbbbbbb", },
        new { QuotationItemId = 84, ParentId = (int?)null, Description = "nnnnnnnnnnnnn", },
    };
    

    而且,使用 LINQPad,查找的工作方式如下:

    var lookup = items.ToLookup(x => x.ParentId);
    
    lookup[58].Dump();
    lookup[60].Dump();
    

    您应该注意,它不会一直递归下去。

    如果你想一直递归,那么你需要定义一个递归函数。试试这个:

    Func<IEnumerable<Quotation>, IEnumerable<Quotation>> recurse = null;
    recurse = qs =>
    {
        return
            qs
                .Concat(
                    from q in qs
                    from q2 in recurse(lookup[q.QuotationItemId])
                    select q2);
    };
    
    recurse(lookup[57]).Dump();
    

    这给了你:

    这是我认为你所期待的。

    【讨论】:

    • +1! ToLookup() 是许多人不知道的那些隐藏的小宝石之一。
    • @Enigmativity - 它似乎并没有将所有级别横向向下仅比 parentId 级别低一级
    • @trailerman - 它确实遍历(不是横向)一直向下。我经常使用这种技术。
    • @Enigmativity - 请查看已编辑的问题 我不知道为什么它也没有按照我的预期工作。
    【解决方案2】:

    您可以简单地选择它们:

    var kids = from p in db.Items
               where p.parentId == parentId
               select p
    

    然后您将拥有:kids.Items 作为列表。所以你可以通过一个简单的foreach 循环来检索孩子,如下所示:

    foreach(Item item in kids.Items)
    

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-10
      • 2019-05-30
      • 1970-01-01
      • 1970-01-01
      • 2017-09-05
      • 2011-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多