使用Linq查询分层表/复合模式中的终端/叶节点

时间:2009-01-05 23:43:40

标签: linq-to-sql design-patterns composite hierarchical

我有一个带有Id,CategoryName和ParentId的自引用表。这是类别层次表的典型场景,它们本身可以分为类别,DB专家告诉我这些类别称为邻接模型。

我想要的是使用Linq to SQL来查询本身与其他子类别无关的子类别,即它们是某个给定类别或子类别的直接叶节点。

简单的部分,我得到了,这只是获得子类别。将代码放在这里几乎不好意思。但我们确实喜欢看代码..

IList<Categories> subcategories = context.Where( c => c.ParentId == 1).ToList();  

但是将它缩小到没有子类别的类别会让我感到困惑。任何帮助将不胜感激。

谢谢你的帮助。 杰夫

UPDATE ** 这似乎有效,但如果有人能证实它是“适当的”,我将不胜感激。所以,如果我想要叶子节点在Id = 1的类别下,我会这样做:

Categories.Where( c => !c.Children.Any ( d => d.ParentId == c.Id)).Where( e => e.ParentId == 1) 

“Children”是Linq给出自引用关联的名称。

2 个答案:

答案 0 :(得分:2)

您的解决方案是正确的,因为Any()方法转换为sql“EXISTS()”函数 并且!c.Children.Any ( d => d.ParentId == c.Id))转换为类似于NOT EXISTS (SELECT * FROM Categories WHERE ParentID = outerRef.ID)

的sql子句

另一种方法是使用Count

Categories.Where( c => c.Children.Count(d => d.ParentId == c.Id) == 0).Where( e => e.ParentId == 1)

但是通常EXISTS()优先于sql中的COUNT()(出于性能原因)所以使用Any()的解决方案应该是正确的。

答案 1 :(得分:0)

我认为如果我正确地理解了你的问题,那么你试图获得所有没有孩子的子元素...这个查询自己将表连接到自身以测试该节点是否用作父节点,如果不是那么它会显示在结果中。

我不确定这是否有效,因为我没有对它进行测试......

   (from c in context
    join cc in context on c.id equals cc.parentid into temp
    from t in temp.DefaultIfEmpty()
    where t == null
    select c).ToList()