如何使用Entity框架进行递归加载?

entity entity-framework load recursion

我在带有TreeNodes表的DB中有一个树结构。该表有nodeId,parentId和parameterId。在EF中,结构类似于TreeNode.Children,其中每个子节点都是TreeNode ...我还有一个包含id,name和rootNodeId的Tree表。

在一天结束时,我想将树加载到TreeView中,但我无法想象如何一次加载它。我试过了:

var trees = from t in context.TreeSet.Include("Root").Include("Root.Children").Include("Root.Children.Parameter")
        .Include("Root.Children.Children")
                        where t.ID == id
                        select t;

这将使我成为前两代而不是更多。如何使用所有代和其他数据加载整个树?

热门答案

我最近遇到了这个问题,在找到一个简单的方法来实现结果之后偶然发现了这个问题。我提供了一个编辑克雷格的答案,提供了第四种方法,但权力 - 决定它应该是另一个答案。这对我来说没问题 :)

我的原始问题/答案可以在这里找到。

只要表中的项目都知道它们属于哪个树(在您的情况下它看起来像是这样的: t.ID ), t.ID 。这就是说,什么实体,你真的有在玩,但即使你有一个以上的目前还不清楚,你必须有一个FK在实体Children如果这不是一个TreeSet

基本上,只是不要使用Include()

var query = from t in context.TreeSet
            where t.ID == id
            select t;

// if TreeSet.Children is a different entity:
var query = from c in context.TreeSetChildren
            // guessing the FK property TreeSetID
            where c.TreeSetID == id
            select c;

这将返回树的所有项目,并将它们全部放在集合的根目录中。此时,您的结果集将如下所示:

-- Item1
   -- Item2
      -- Item3
-- Item4
   -- Item5
-- Item2
-- Item3
-- Item5

既然你可能希望你的实体只是分层次地从EF出来,这不是你想要的,对吧?

..然后,排除存在于根级别的后代:

幸运的是,因为模型中有导航属性,所以仍然会填充子实体集合,如上面结果集的图示所示。通过使用foreach()循环手动迭代结果集,并将这些根项添加到new List<TreeSet>() ,您现在将拥有一个包含根元素的列表,并且所有后代都已正确嵌套。

如果你的树变大并且性能是一个问题,你可以通过ParentID对它的返回集ParentID进行排序(它是Nullable ,对吧?),这样所有的根项都是第一个。像以前一样迭代和添加,但是一旦你得到一个非空的,就会从循环中断开。

var subset = query
     // execute the query against the DB
     .ToList()
     // filter out non-root-items
     .Where(x => !x.ParentId.HasValue);

现在subset将如下所示:

-- Item1
   -- Item2
      -- Item3
-- Item4
   -- Item5



关于克雷格的解决方案:

  1. 真的不想使用延迟加载!围绕n + 1查询的必要性而设计的设计将成为主要的性能吸引力。
  2. *********( 嗯,公平地说,如果你要允许用户有选择地向下钻取树,那么它可能是合适的。只是不要使用延迟加载来使它们全部运行起来前线!!

  3. 我从来没有尝试过嵌套的设置,我也不会建议破解EF配置来使这项工作,因为有一个更容易的解决方案。

  4. 另一个合理的建议是创建一个提供自链接的数据库视图,然后将该视图映射到中间连接/链接/ m2m表。就个人而言,我发现这个解决方案比必要的更复杂,但它可能有它的用途。



许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因
许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因