2017-08-24 80 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