LINQ:链ID从一行到另一行

时间:2011-09-03 03:34:50

标签: c# .net linq linq-to-sql

我有一张桌子,里面有一个child-gt; child->父级。 (这是一个在现有旧数据库上使用的补丁,所以它有点狡猾)。

表的类:

public class Foo
{
    int ID {get;set;}
    int ParentID  {get;set;}
    int BaseParentID {get;set;}
}

假设我在那里有一些记录

ID: 10, ParentID: 5, BaseParentID: 5
ID: 05, ParentID: 1, BaseParentID: 5
ID: 01, ParentID: 1, BaseParentID: 0

我想要做的是获取每个ParentID,直到baseparentid为0.所以在某种程度上,它从一个记录到另一个记录逐步执行,并将其检索到ID的列表中。

最终结果应该是一个列表:{ 10, 5, 1 }

这就是我现在正在做的事情(目前限制为4,但如果没有限制,我更喜欢它):

var list = new List<int?>();
var id = 10; // The first ID is given when this method is started.
list.Add(id);
int? pid = db.Foo.Where(w => w.ID == id).Single().BaseParentID; // i have this as a compiled query function
if (pid != 0) {
    list.Add(pid);
    pid = db.Foo.Where(w => w.ID == pid).Single().BaseParentID; //  for the sake of this example i'm just using the query here
    if (pid != null) {
         list.Add(pid);
         // And so on
    }
}

正如您所看到的,这是一种蹩脚的方式。但我不确定是否有办法在花哨的linq查询中执行此操作。

PS。这一点是一种伪文件夹结构。

2 个答案:

答案 0 :(得分:3)

这是一个很好的例子,你可以在哪里写一个单独的iterator function

 IEnumerable<Foo> TraverseParents(Foo foo, IEnumerable<Foo> all)
 {
      while(foo != null) 
      {
          yield return foo;
          foo = (foo.pid == 0) ? null : all.FirstOrDefault(f => f.ID == foo.pid);
      }
 }

 // In the calling code
 var id = 10;
 Foo root = db.Foo.FirstOrDefault(f => f.ID == id);
 List<int> list = TraverseParents(root, db.Foo)
                   .Select(f => f.ID)
                   .ToList();

答案 1 :(得分:1)

您可以使用以下方法:

List<int> GetParentHierarchy(int startingId)
{
  List<int> hierarchy = new List<int> { startingId };
  using(Connection db = new Connection()) //change to your context
  {      
      int parentId = startingId;
      while(true)
      {
         var foo = db.Foo(x => x.Id == parentId).SingleOrDefault(); 
         if(foo == null)
           break;
         parentId = foo.ParentId;
         hierarchy.Add(foo.Id);
         if(foo.BaseParentID == 0)
           break;
      }
  }

  return hierarchy;

}