2012-06-24 102 views
1

通过Id,parentId描述获得数据表。它是一个关系表结构。Datatable和LINQ父/子关系

我想能够传递一个参数给一个函数,该函数是树状视图中当前选择的项目标识。我想有一个DataTable的所有相关儿童返回的行,关系的顶部是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(); 

Data dump

回答

5

这是你可以做什么:

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(); 

Screen Dump from LINQPad

你应该注意,不会一路下调。

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

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(); 

而且,让你:

LINQPad Image Dump

这是我想你期待。

+2

+1! ToLookup()是许多人不知道的隐藏的小宝石之一。 –

+0

如果孩子有孩子,这个横向会进一步下降吗? – trailerman

+0

@trailerman - 是的,它会一路向下。 – Enigmativity

-1

你可以简单地选择他们:

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

然后你将有:kids.Items作为一个名单。所以,你可以通过一个简单的foreach循环这样的检索孩子:

foreach(Item item in kids.Items) 

希望它能帮助。