【问题标题】:MVC 5 Entity Framework 6 - deleting nested / hierarchical dataMVC 5 Entity Framework 6 - 删除嵌套/分层数据
【发布时间】:2016-12-03 13:19:31
【问题描述】:

在处理分层数据并尝试删除具有子节点的节点时,我遇到了一些麻烦。

我已经建立了一个类似于this article 的示例树,并用一点引导程序(添加、删除和编辑图标)装饰了 ul-li 项目。

我现在在递归删除中苦苦挣扎,因为我使用的是 IEnumerable (Children),它是 parentNodeID 的逆结果。所以当删除一个节点时,子节点被更新并且系统抛出一个枚举错误(集合已经改变)。几年前我有过这样的错误,但我不记得我是如何修复它的。有什么建议吗?

这就是我得到的:

~/Models/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; }
}

~/Controllers/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

【问题讨论】:

  • 收藏已更改?尝试在DeleteRecursive 方法中使用for 循环而不是foreach 循环。
  • 啊,我有一个更好的解决方案,而不是使用 for 循环(这有点老派恕我直言)。
  • for 的老派是什么?现在您创建一个不需要的数组。无论如何,如果您解决了自己的问题,您可以为自己的问题写一个答案,甚至在适当的时候将其标记为已接受。

标签: c# entity-framework recursion asp.net-mvc-5 hierarchical-data


【解决方案1】:
public void DeleteRecursive(Tree tree)
{
    foreach(var child in tree.Children.ToArray<Tree>())
    {
        DeleteRecursive(child);
    }
    db.Trees.Remove(tree);
}

使用数组进行删除不会改变原始集合。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 2015-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多