是否可以将List转换为Tree,以便在删除父节点时自动删除所有子节点?
这样做的原因是我有递归类别,我希望显示除子类别之外的所有类别(递归),并且在我的脑海中最简单的方法是执行类似图片中的操作。
正如您在此场景中看到的,当我删除红色节点时,所有绿色节点都将自动删除。我有什么选择?
这是我正在使用的模型,如果它有任何区别。
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);
。这将消除当前类别(在图片中它将删除红色的一个)但是绿色的类别将保留。
我如何确保如果删除红色的那个绿色也会删除?
最后,我想要一张包含图片中所有黑色项目的列表。
答案 0 :(得分:1)
要删除项目,您需要逐个删除它们;这就是db上下文的工作原理。你可以简单地删除所有要删除的项目。以下是遍历树的简单算法:
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;
}
答案 1 :(得分: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;
}