1

是否可以将列表转换为树,以便当我删除父节点时,所有子节点都会被自动删除?

这样做的原因是我有递归类别,我想显示除子类别(递归)之外的所有类别,我认为最简单的方法是执行图片中的操作。

正如您在这种情况下看到的,当我删除红色节点时,所有绿色节点都会自动删除。我有哪些选择?

树

这是我正在使用的模型,如果它有什么不同的话。

public class Category
{
    public int Id { get; set; }

    public int? RootCategoryId { get; set; }
    public virtual Category RootCategory { get; set; }
    public virtual ICollection<Category> ChildCategories { get; set; }
}

这是我到目前为止所拥有的

// This would eliminate only current category but not its children = bad
var availableCategories = _db.Categories.Where(x => x.Id != currentlyEditedId);

因此,例如,当我想编辑一个类别时,我会调用_db.Categories.Where(x => x.Id != currentlyEditedId);. 这将消除当前类别(在图片中它将删除红色类别),但绿色类别将保留。

我如何确保如果我删除红色的,绿色的也会删除?

最后,我想要一个包含图片中所有黑色项目的列表。

4

2 回答 2

1

要删除一个项目,您需要单独删除每个项目;这就是数据库上下文的工作方式。不过,您可以简单地删除所有项目。这是遍历树的简单算法:

public static IEnumerable<Category> Traverse(Category root)
{
    var stack = new Stack<Category>();

    stack.Push(root);

    while (stack.Any())
    {
        var next = stack.Pop();
        yield return next;
        foreach (var child in next.ChildCategories)
            stack.Push(child);
    }
}

现在您可以执行以下操作:

public static void DeleteCategory(Category category)
{
    var items = Traverse(category).ToList();
    var itemsToDelete = _db.Categories.Where(cat => items.Contains(cat));
    //delete items
}

如果您只想从它的内存集合中删除一个项目,则只需要调用Remove它的父项。如果您没有父节点,并且只有要删除的节点和根节点,那么您将需要另一种方法来遍历树:

public static bool Remove(Category root, int id)
{
    var stack = new Stack<Category>();

    stack.Push(root);

    while (stack.Any())
    {
        var next = stack.Pop();
        foreach (var child in next.ChildCategories)
        {
            if (child.Id == id)
            {
                next.ChildCategories.Remove(child);
                return true;
            }
            stack.Push(child);
        }
    }

    return false;
}
于 2013-06-28T19:33:59.610 回答
1

这就是我想要的。传入类别列表并删除当前类别并递归删除其所有子项。

/// <summary>
/// Get list of all categories except current one as well as all it's child categories
/// </summary>
/// <param name="id">Current category id</param>
/// <param name="categories">List of categories</param>
/// <returns>List of categories</returns>
public static List<Category> CategoriesWithoutChildren(int id, List<Category> categories)
{
    var currentCategory = categories.Single(x => x.Id == id);
    categories.Remove(currentCategory);

    if (currentCategory.ChildCategories.Count > 0)
    {
        currentCategory.ChildCategories.ToList().ForEach(x =>
        {
            categories = CategoriesWithoutChildren(x.Id, categories);
        });
    }

    return categories;
}
于 2013-06-29T12:04:56.597 回答