c# - Linq 类别和子类别

标签 c# linq

问题是我不明白如何使用 LINQ 获取所有类别和子类别并将它们添加到列表中以便在 View 中显示它们。

public class Category
{
    public int ID { get; set; }
    public string Title { get; set; }
    public int? ParentID { get; set; }
    public virtual Category Parent { get; set; }
}

目前我只有这个方法可以获取所有的类别。

public async Task<IEnumerable<Category>> GetAllCategories()
    {
        return await _context.Categories.ToListAsync();
    }

这是我想要实现的:

output

最佳答案

所以,如果我从这些数据开始:

var categories = new List<Category>()
{
    new Category() { ID = 0, ParentID = null, Title = "First Link" },
    new Category() { ID = 1, ParentID = null, Title = "Second Link" },
    new Category() { ID = 2, ParentID = null, Title = "Third Link" },
    new Category() { ID = 3, ParentID = null, Title = "Fourth Link" },
    new Category() { ID = 4, ParentID = null, Title = "Fifth Link" },
    new Category() { ID = 5, ParentID = 0, Title = "First Child Link" },
    new Category() { ID = 6, ParentID = 0, Title = "Second Child Link" },
    new Category() { ID = 7, ParentID = 0, Title = "Third Child Link" },
    new Category() { ID = 8, ParentID = 6, Title = "First Grandchild Link" },
    new Category() { ID = 9, ParentID = 6, Title = "Second Grandchild Link" },
    new Category() { ID = 10, ParentID = 6, Title = "Third Grandchild Link" },
};

...那么我可以这样做:

var lookup = categories.ToLookup(x => x.ParentID);

这会创建一个可用于查找任何父 ID 的所有子代的查找。在您的情况下,您应该能够执行 _context.Categories.ToLookup(x => x.ParentID);。您可能需要在 .ToLookup 之前弹出一个 .ToArray()

好处是这只会访问数据库一次。

现在递归遍历数据变得容易了。以下是三种方法:

(1)

Func<ILookup<int?, Category>, int?, int, IEnumerable<string>> formatTree = null;
formatTree = (l, p, i) =>
    from c in l[p]
    from t in new[] { "".PadLeft(i * 4) + c.Title }.Concat(formatTree(l, c.ID, i + 1))
    select t;

(2)

public IEnumerable<string> FormatTree(ILookup<int?, Category> lookup, int? parent, int indent)
{
    return
        from c in lookup[parent]
        from t in new[] { "".PadLeft(indent * 4) + c.Title }.Concat(FormatTree(lookup, c.ID, indent + 1))
        select t;
}

(3)

public IEnumerable<string> FormatTree2(ILookup<int?, Category> lookup, int? parent, int indent)
{
    foreach (var category in lookup[parent])
    {
        yield return "".PadLeft(indent * 4) + category.Title;
        foreach (var descendant in FormatTree2(lookup, category.ID, indent + 1))
        {
            yield return descendant;
        }
    }
}

这三者都以相同的方式做同样的事情,只是语法不同而已。

我得到这个输出:

First Link 
    First Child Link 
    Second Child Link 
        First Grandchild Link 
        Second Grandchild Link 
        Third Grandchild Link 
    Third Child Link 
Second Link 
Third Link 
Fourth Link 
Fifth Link 

不清楚您的确切输出是什么 - 我假设您不希望创建 PNG 图像 - 但您应该能够使用它来获得您需要的东西。

关于c# - Linq 类别和子类别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35820398/

相关文章:

c# - 确定通用列表之间的差异

c# - 返回 IQueryable 表达式而不执行数据库查询

c# - 有没有办法在不解压的情况下打开zip文件中的文件(c#)

c# - Log4Net 未在 MaxFileSize 上滚动

c# - 为什么我不能将类库项目引用添加到 Silverlight 项目?

c# - 将 Func<T, bool> 传递给 LINQ Where

c# - 我想知道在迭代数据读取器对象时连接状态和 'yield' 对代码性能的影响

c# - 如何判断 JSON 结果是对象还是数组?

c# - 线程和 IEnumerable; "Collection Was Modified"- 异常

c# - Javascript 警报不显示