| ID | PrID | Name |
|------------------|
| 1 | null | N1 |
| 2 | 1 | N2 |
| 3 | 2 | N3 |
| 4 | 3 | N4 |
您好,我有以下自引用数据表。我的输入参数是N1,我需要找到它的最后一个孩子N4。请帮忙写LINQ查询。 谢谢!
答案 0 :(得分:0)
这个问题非常相似。基本上你需要编写一个扩展方法,因为LINQ不是为处理这样的场景而设计的。
答案 1 :(得分:0)
不是最好的LINQ候选者,但是,这个递归扩展应该有效:
public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse)
{
foreach (T item in source)
{
yield return item;
IEnumerable<T> seqRecurse = fnRecurse(item);
if (seqRecurse != null)
{
foreach (T itemRecurse in Traverse(seqRecurse, fnRecurse))
{
yield return itemRecurse;
}
}
}
}
以下是您的示例数据:
DataTable tbldata = new DataTable();
tbldata.Columns.Add("ID", typeof(int));
tbldata.Columns.Add("PrID", typeof(int));
tbldata.Columns.Add("Name", typeof(string));
tbldata.Rows.Add(1, null, "N1");
tbldata.Rows.Add(2, 1, "N2");
tbldata.Rows.Add(3, 2, "N3");
tbldata.Rows.Add(4, 3, "N4");
此查询返回您想要的结果:
string parentName = "N1";
IEnumerable<DataRow> rows = tbldata.AsEnumerable();
DataRow parentRow = rows.FirstOrDefault(r => r.Field<string>("Name") == parentName);
DataRow lastChild = null;
if(parentRow != null)
{
int parentID = parentRow.Field<int>("ID");
lastChild = rows.Where(r => r.Field<int?>("PrID") == parentID)
.Traverse(parent => rows
.Where(child => child.Field<int?>("PrID") == parent.Field<int>("ID")))
.LastOrDefault();
}
输出:
Console.Write(String.Join(",", lastChild.ItemArray)); // 4,3,N4
答案 2 :(得分:-1)
这在LINQ中可能是可撤消的。
您可以创建一个存储过程,使用WHILE
循环来查找最后一个子节点,也可以将整个表拉到应用程序并使用循环解析它
Item i = FetchFirst();
while (i.GetNext() != null)
i = i.GetNext();
然后i
将存储结果。 GetNext()
加载下一项,FetchFirst()
加载N1项。