使用唯一的 LINQ 查询选择所有相关实体。

14 浏览
0 Comments

使用唯一的 LINQ 查询选择所有相关实体。

我有一个Category表,其中有一个自我关联关系。也就是说,它是一种树形层次结构的视图,例如:oldfather_category -> father_category -> child_category。

所以我需要在这个表上构建树形视图。我需要全部的行。首先我这样做:

    IEnumerable list = _service.Get().Where(c => c.ParentID == null);
    Node(list);

当我像这样使用递归:

    private void Node(IEnumerable list)
    {
        foreach (Category c in list)
        {
            //如果有子项
            if (c.Category1.Count > 0)
                Node(c.Category1);
        }
    }

当我调用c.Category1.Count属性时,实体框架每次都会构建查询(延迟执行的魔法)。但是我想在第一条语句中加载所有实体,我只想向SQL服务器发送一次查询。我该怎么做?希望问题清楚明了)

编辑:当我使用ToList()时,Category1属性为空。

0
0 Comments

问题的原因是无法使用仅使用LINQ查询来加载树中的所有元素。要加载树中的所有元素,需要在数据库服务器上编写一个函数来循环遍历所有子元素。但是,根据实际需要运行的查询,可能可以通过一些方法来解决这个问题。如果特定元素将始终是任何树的根元素,可以在每个元素上添加第三个引用指向树的根,并在内存中构建实际的树结构。例如,在博客的评论中,博客帖子的ID可能始终是树的根,然后每个评论仍然有一个指向其所回应的父元素的引用。在每个元素上添加一个根标识符,并查询该标识符,然后在内存中递归地构建树。

如果查询的根不是预定义类型的元素,最好编写一个函数来处理这种情况。但是,这样做将无法使用Entity Framework进行此查询。

以下是一种可能的解决方法:

public class TreeNode

{

public int Id { get; set; }

public int ParentId { get; set; }

public int RootId { get; set; }

// other properties

}

public List GetAllNodes(int rootId)

{

List nodes = new List();

using (var context = new YourDbContext())

{

nodes = context.TreeNodes.Where(node => node.RootId == rootId).ToList();

}

return nodes;

}

public TreeNode BuildTree(List nodes, int rootId)

{

TreeNode root = nodes.FirstOrDefault(node => node.Id == rootId);

if (root != null)

{

root.Children = BuildChildren(nodes, root.Id);

}

return root;

}

public List BuildChildren(List nodes, int parentId)

{

List children = new List();

foreach (var node in nodes.Where(node => node.ParentId == parentId))

{

node.Children = BuildChildren(nodes, node.Id);

children.Add(node);

}

return children;

}

// Usage:

int rootId = 1; // the root id for your query

List allNodes = GetAllNodes(rootId);

TreeNode tree = BuildTree(allNodes, rootId);

这个解决方法通过先从数据库中获取所有与根节点相关的节点,然后在内存中递归构建树结构来实现。

0