Linq将外部联接留在同一列表中以查找叶节点

时间:2011-06-06 12:18:16

标签: c# linq tree

我有一个内存List<TreeNode>。是否可以使用linq选择所有叶节点?

SQL看起来像这样:

SELECT      
    t1.Name
FROM 
    Tree t1 
    LEFT JOIN Tree t2 
        ON t1.UserId = t2.ParentId  
WHERE 
    t2.UserId is null

我得到的最接近的是(我仍然需要过滤掉空值):

                       var test = from t1 in list
                       join t2 in list
                       on t1.UserId equals t2.ParentId into g                   

                       from result in g.DefaultIfEmpty()          

                       select new { 
                       t1.Name
                       };

在没有where子句的情况下生成正确的sql(在linqpad中测试时)。我无法访问t2,如果我尝试在t2 == null的地方过滤结果,我选择匿名对象。我是否需要创建列表的副本并加入其中?

2 个答案:

答案 0 :(得分:2)

编辑:好的,我以前误解了。所以你基本上在列表中的项目(t1)之后没有元素t2,而t1.UserId == t2.ParentId?在这种情况下,我建议您使用:

我怀疑你想要:

var test = from t1 in list
           join t2 in list
              on t1.UserId equals t2.ParentId into g
           where !g.Any()
           select t1.Name;

请注意,我之前没有使用匿名类型,因为您只选择一个值。

另一种选择是:

var parents = new HashSet<Guid>(list.Where(x => x.ParentId != null)
                                    .Select(x => x.ParentId.Value));
var query = list.Where(t1 => !parents.Contains(t1.UserId));

答案 1 :(得分:0)

试试这个:

var test = from t1 in list
           join t2 in list
           on t1.UserId equals t2.ParentId into g                   
           from result in g.DefaultIfEmpty()          
           where t2.UserId == null
           select new { 
               t1.Name
           };