2017-08-24 84 views
1

我有一个从存储过程构建的菜单,它返回一个文件夹层次结构。该过程返回FolderID,Name和ParentID。在我的菜单资源库中,我在文件夹列表上使用了ForEach()来添加与父文件夹关联的每个子文件夹。使用Linq删除同一对象中的孩子的父母

它看起来像这样:

folders = await _dbcontext.MenuFolders.FromSql("EXEC UserMenuFolders @p0", UserID) 
    .Select(x => new MenuFolder 
     { 
      FolderID = x.FolderID, 
      FolderName = x.FolderName, 
      SortOrder = x.SortOrder, 
      SubofID = x.SubofID 
     })  
    .ToListAsync(); 

folders.ForEach(x => x.SubFolders = folders 
    .Where(y => y.SubofID == x.FolderID) 
    .OrderBy(y => y.SortOrder) 
    .ToList()); 

这给了我一个对象,它看起来有点像:

"Folder 1": { 
    "Sub Folder 1": [ 
     "SubFolder 1.1", 
     "SubFolder 1.2" 
    ], 
    "Sub Folder 2": [ 
     "SubFolder 2.1", 
     "SubFolder 2.2" 
    ] 
}, 
"Folder 2": { 
    //Other sub Folders 
}, 
"SubFolder 1":{}, 
"SubFolder 1.1":{}, 
"SubFolder 1.2": {} 

你可以看到,子文件夹都在那里两次,因为初始查询得到所有文件夹。我如何从列表中删除子文件夹的文件夹?另外,我很想看看是否有更高效的方法来创建这个菜单结构,但请记住我必须使用存储过程,因为授权逻辑已经在那里建立了。

这是我认为没有做任何愚蠢的尝试:

folders.RemoveAll(x => x.SubFolders.Any(c=> c.FolderID == x.FolderID)); 

而下面是我的MenuFolders实体:

public int FolderID { get; set; } 
public string FolderName { get; set; }   
public int ParentID { get; set; } 
[ForeignKey("ParentID")] 
public List<MenuFolder> SubFolders { get; set; } 
public Int16 SortOrder { get; set; } 
+0

你想从样本中删除哪个'SubFolder 1.1'?第一个还是第二个? _请包含'UserMenuFolders'的源代码._ – mjwills

+0

第二个。如果该文件夹在ForEach后成为孩子,我想将其删除。 – Eric

回答

2

你接近你的尝试。基本上,你想要删除的是儿童文件夹。这意味着如果文件夹的父ID存在任何文件夹的ID,它必须是一个孩子,因此你可以安全地删除它。

folders.RemoveAll(x => folders.Any(f => f.FolderID == x.ParentID)); 
+1

哇,我在踢自己!感谢@ Travis,它的工作! – Eric

+1

这些层次结构有时可能会涉及到工作,我在@Eric之前做过类似的事情:) –

1

只要使用递归。假设根文件夹(文件夹没有父母)已经ParentId == 0,你可以使用这样的事情:

public static List<MenuFolder> ToTree(IEnumerable<MenuFolder> flatList, int parentId = 0) 
{ 
    var tree = flatList 
     .Where(m => m.ParentID == parentId) 
     .ToList(); 

    tree.ForEach(t => t.SubFolders = ToTree(flatList, t.FolderID)); 

    return tree; 
} 

,就回到:

var foldersTree = ToTree(folders); 

注:这将创建任何深度的树形结构(不只是在你的例子中的两个级别)

+0

@Federico效果很好。谢谢! – Eric

+0

尽管如此,请记住,我的示例只有两个级别,但我的解决方案还创建了一个像您一样的深度的树。但是,在您的解决方案中,您不必像我使用RemoveAll方法调用一样切断任何脂肪。很好的答案,谢谢! – Eric