使用唯一的 LINQ 查询选择所有相关实体。
使用唯一的 LINQ 查询选择所有相关实体。
我有一个Category表,其中有一个自我关联关系。也就是说,它是一种树形层次结构的视图,例如:oldfather_category -> father_category -> child_category。
所以我需要在这个表上构建树形视图。我需要全部的行。首先我这样做:
IEnumerablelist = _service.Get().Where(c => c.ParentID == null); Node(list);
当我像这样使用递归:
private void Node(IEnumerablelist) { foreach (Category c in list) { //如果有子项 if (c.Category1.Count > 0) Node(c.Category1); } }
当我调用c.Category1.Count属性时,实体框架每次都会构建查询(延迟执行的魔法)。但是我想在第一条语句中加载所有实体,我只想向SQL服务器发送一次查询。我该怎么做?希望问题清楚明了)
编辑:当我使用ToList()时,Category1属性为空。
问题的原因是无法使用仅使用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
{
List
using (var context = new YourDbContext())
{
nodes = context.TreeNodes.Where(node => node.RootId == rootId).ToList();
}
return nodes;
}
public TreeNode BuildTree(List
{
TreeNode root = nodes.FirstOrDefault(node => node.Id == rootId);
if (root != null)
{
root.Children = BuildChildren(nodes, root.Id);
}
return root;
}
public List
{
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
TreeNode tree = BuildTree(allNodes, rootId);
这个解决方法通过先从数据库中获取所有与根节点相关的节点,然后在内存中递归构建树结构来实现。