与Linq一起走层次结构表

时间:2010-04-01 12:36:38

标签: c# linq-to-entities

我有一个包含两列的表,GroupId和ParentId(都是GUIDS)。该表形成一个层次结构,所以我可以在“GroupId”字段中查找一个值,当我找到它时,我可以查看它的ParentId。此ParentId也将出现在不同记录的GroupId中。我可以使用它从任何点向上遍历层次结构树(root是一个空的GUID)。我想要做的是在我知道GroupId时获取记录列表。这将是GroupId和所有父母返回根记录的记录。 Linq是否可以实现这一点?如果是这样,任何人都可以提供代码片段吗?

3 个答案:

答案 0 :(得分:5)

LINQ不是为处理递归选择而设计的。

当然可以编写自己的扩展方法来补偿LINQ to Objects中的扩展方法,但我发现LINQ to Entities不喜欢不容易转换为SQL的功能。

修改 有趣的是,LINQ to Entities并没有抱怨Matt Warren使用LINQ here进行递归。你可以这样做:

var result = db.Table.Where(item => item.GroupId == 5)
                     .Traverse(item => db.Table.Where(parent 
                                                       => item.ParentId == parent.GroupId));

使用此处定义的扩展方法:

static class LinqExtensions
{
    public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source,
                                             Func<T,IEnumerable<T>> selector){
    foreach(T item in source){
        yield return item;
        IEnumerable<T> children = selector(item);
        foreach (T child in children.Traverse(selector))
        {
            yield return child;
        }
    }
}

但是,表演可能很差。

答案 1 :(得分:1)

Linq肯定是可能的,但你必须为heirarchy中的每个级别进行数据库调用。不完全是最佳的。

答案 2 :(得分:0)

其他受访者是对的 - 因为你必须进行多次往返,所以表现相当差。这在某种程度上取决于您的具体情况,但是 - 您的树很深,例如,人们会经常执行此操作。

通过创建执行此操作的存储过程(使用CTE)并在实体设计器中将其连接起来以返回您特别定义的实体,可以很好地为您提供服务。