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); 
} 

使用数组中进行删除不改变原来的集合。