我有一张桌子,里面有一个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。这一点是一种伪文件夹结构。
答案 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;
}