我在数据库中有一个表格如下:
MenuItem
-------------
MenuItemId 1 --------+
MenuItemName |
ParentId * --------+
现在我编写了一个递归函数来获取所有父MenuItems及其子项。
private ICollection<MenuItem> GetAllChildrenOfSpecificMenuItemRecursively(MenuItem menuItem, IEnumerable<MenuItem> menuItems)
{
ICollection<MenuItem> Children = null;
foreach (MenuItem mi in menuItems)
{
if (mi.ParentMenuItemId != null)
{
if (mi.ParentMenuItemId == menuItem.MenuItemId)
{
Children.Add(mi);
}
else
{
return GetAllChildrenOfSpecificMenuItemRecursively(mi, menuItems);
}
}
}
return Children;
}
现在,我从另一个函数调用它,如下所示:
public IEnumerable<MenuItem> GetAllParentMenuItemsWithChildren()
{
List<MenuItem> MenuItems = new List<MenuItem>();
IEnumerable<MenuItem> AllMenuItems = null;
using (MaxContext entityContext = new MaxContext())
{
AllMenuItems = (from e in entityContext.MenuItemSet select e).ToList();
foreach (MenuItem menuItem in entityContext.MenuItemSet)
{
if (menuItem.ParentMenuItemId == null)
{
menuItem.Children = GetAllChildrenOfSpecificMenuItemRecursively(menuItem, AllMenuItems);
MenuItems.Add(menuItem);
}
}
}
return MenuItems;
}
但是它在递归函数中给了我stackoverflowException。我确信我在这个功能上犯了一个小错误。任何人都可以指出这个错误吗?
答案 0 :(得分:3)
您的GetAllChildrenOfSpecificMenuItemRecursively()
始终使用mi
进行递归。它应该用mi.ParentMenuItemId
代替。
答案 1 :(得分:1)
为什么总是将相同的menuItems
收藏品传递给递归函数?
你的代码应该是:
private IEnumerable<MenuItem> GetAllChildrenOfSpecificMenuItemRecursively(MenuItem menuItem)
{
var children = new List<MenuItem>();
foreach (MenuItem mi in menuItem.Children)
{
// Why are you checking this?
if (mi.ParentMenuItemId != null)
{
// Why are you checking this?
if (mi.ParentMenuItemId == menuItem.MenuItemId)
{
children.Add(mi);
}
else
{
children.AddRange(GetAllChildrenOfSpecificMenuItemRecursively(mi))
}
}
}
return Children;
}
从方法名称来看,这就是它应该做的所有事情:
private IEnumerable<MenuItem> GetAllChildrenOfSpecificMenuItemRecursively(MenuItem menuItem)
{
var children = new List<MenuItem>();
if (menuItem.Children == null) return children;
foreach (MenuItem mi in menuItem.Children)
{
children.Add(mi);
children.AddRange(GetAllChildrenOfSpecificMenuItemRecursively(mi));
}
return Children;
}
修改强>
public class MenuItem
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
public virtual MenuItem Parent { get; set; }
[InverseProperty("Parent")]
public virtual ICollection<MenuItem> Children { get; set; }
}
答案 2 :(得分:1)
我认为在不使用递归的情况下,有一种更简单(也许更快)的方法。像这样:
public ICollection<MenuItem> GetMenuItemsAsTreeList()
{
AllMenuItems = entityContext.MenuItemSet.ToList();
Dictionary<int, MenuItem> dic = AllMenuItems.ToDictionary(n => n.Id, n => n);
List<MenuItem> rootMenuItems = new List<MenuItem>();
foreach (MenuItem menuItem in AllMenuItems)
{
if (menuItem.ParentMenuItemId.HasValue)
{
MenuItem parent = dic[menuItem.ParentMenuItemId.Value];
menuItem.ParentMenuItem = parent;
parent.SubMenuItems.Add(menuItem);
}
else
{
rootMenuItems.Add(menuItem);
}
}
return rootMenuItems;
}