1

當玩分層數據並嘗試刪除有子節點的節點時,我遇到了一些麻煩。MVC 5實體框架6 - 刪除嵌套/分層數據

我設置了一個類似於this article的樣例樹,並使用一點引導(添加,刪除和編輯圖標)來裝飾ul-li項目。

我現在在遞歸刪除,因爲我正在使用IEnumerable(Children),這是parentNodeID的反向結果struggeling。所以當刪除一個節點時,子節點被更新並且系統拋出一個枚舉錯誤(集合已經改變)。幾年前我有過這樣的錯誤,但我不記得,我是如何修復它的。有什麼建議?

因此,這裏是我得到:

〜/型號/ Tree.cs

public class Tree 
{ 
    [Key] 
    public int NodeID { get; set; } 

    [Display(Name ="Element name")] 
    public string NodeName { get; set; } 

    [Display(Name ="Element identifier")] 
    public string NodeIdentifier { get; set; } 

    public int? ParentNodeID { get; set; } 
    public virtual Tree Parent { get; set; } 
    public virtual ICollection<Tree> Children { get; set; } 
} 

〜/控制器/ TreesController.cs

// Partial - only Delete Actions 

// GET: Trees/Delete/5 
public async Task<ActionResult> Delete(int? id) 
{ 
    if (id == null) 
    { 
     return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
    } 
    Tree tree = await db.Trees.FindAsync(id); 
    if (tree == null) 
    { 
     return HttpNotFound(); 
    } 

    if (tree.Children.Count > 0) 
    { 
     ViewBag.HasChildren = true; 
    } 
    else 
    { 
     ViewBag.HasChildren = false; 
    } 

    return View(tree); 
} 

// POST: Trees/Delete/5 
[HttpPost, ActionName("Delete")] 
[ValidateAntiForgeryToken] 
public async Task<ActionResult> DeleteConfirmed(int id) 
{ 
    Tree tree = await db.Trees.FindAsync(id); 
    DeleteRecursive(tree); 
    db.Trees.Remove(tree); 
    await db.SaveChangesAsync(); 
    return RedirectToAction("Index"); 
} 

public void DeleteRecursive(Tree tree) 
{ 
    foreach(var child in tree.Children) 
    { 
     DeleteRecursive(child); 
    } 
    db.Trees.Remove(tree); 
} 

〜/ Views/Trees/Index.cshtml

<div class="container"> 
@helper BuildTree(IEnumerable<MVCMusicStore.Models.Tree> tree, int? parentID = null) 
{ 
    var nodes = tree.Where(t => t.ParentNodeID == parentID).OrderBy(n => n.NodeIndexOrder); 
    if (nodes.Any()) 
    { 
     if (nodes.First().ParentNodeID == null) 
     { 
       <ul id="tree"> 
        @foreach (var node in nodes) 
        { 
         <li> 
          @node.NodeIndexOrder - @node.NodeName &nbsp; <a href="@Url.Action("Edit","Trees",new { id = node.NodeID })" data-toggle="tooltip" data-placement="right" title="Bearbeiten"><i class="glyphicon glyphicon-edit"></i></a>&nbsp; <a href="@Url.Action("Delete","Trees",new { id = node.NodeID })" data-toggle="tooltip" data-placement="right" title="Löschen"><i class="glyphicon glyphicon-trash"></i></a> 
          @BuildTree(tree, node.NodeID) 
         </li> 
        } 
       </ul> 
     } 
     else 
     { 
       <ul> 
        @foreach (var node in nodes) 
        { 
         <li> 
          @node.NodeIndexOrder - @node.NodeName &nbsp; <a href="@Url.Action("Edit","Trees",new { id = node.NodeID })" data-toggle="tooltip" data-placement="right" title="Bearbeiten"><i class="glyphicon glyphicon-edit"></i></a>&nbsp; <a href="@Url.Action("Delete","Trees",new { id = node.NodeID })" data-toggle="tooltip" data-placement="right" title="Löschen"><i class="glyphicon glyphicon-trash"></i></a> 
          @BuildTree(tree, node.NodeID) 
         </li> 
        } 
       </ul> 
     }   
    } 
    else 
    { 

     <p> 
      <a href="@Url.Action("Create","Trees", new { parentNodeID = parentID })" data-toggle="tooltip" data-placement="right" title="Neu"><i class="glyphicon glyphicon-plus"></i></a> 
     </p> 
    } 
} 

@BuildTree(Model,null) 
</div> 

編輯 - 解決方案:

public void DeleteRecursive(Tree tree) 
{ 
    foreach(var child in tree.Children.ToArray<Tree>()) 
    { 
     DeleteRecursive(child); 
    } 
    db.Trees.Remove(tree); 
} 

使用數組來刪除不改變原來的集合。

Credits to Johnathon Sullinger: Delete item in nested collections of Nth level

+0

收藏已變更?嘗試在'DeleteRecursive'方法中使用'for'循環而不是'foreach'循環。 –

+0

啊,我有一個更好的解決方案,比使用for-loop(這是一箇舊的skool imho)。 – SnakeByte

+0

關於'for'的舊學校是什麼?現在你創建一個你不需要的數組。無論如何,如果你解決了自己的問題,那麼可以爲自己的問題寫一個答案,甚至在適當的時候將其標記爲已接受。 –

回答

0
public void DeleteRecursive(Tree tree) 
{ 
    foreach(var child in tree.Children.ToArray<Tree>()) 
    { 
     DeleteRecursive(child); 
    } 
    db.Trees.Remove(tree); 
} 

使用數組中進行刪除不改變原來的集合。