Avi*_*ush 20 recursion entity load entity-framework
我在带有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;
Run Code Online (Sandbox Code Playgroud)
这将使我成为前两代而不是更多.如何使用所有代和其他数据加载整个树?
Joe*_*aus 15
我最近遇到了这个问题,在找到一个简单的方法来实现结果之后偶然发现了这个问题.我提供了一个编辑克雷格的答案,提供了第四种方法,但权力 - 决定它应该是另一个答案.这对我来说没问题 :)
只要表中的项目都知道它们属于哪个树(在您的情况下看起来像它们那样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;
Run Code Online (Sandbox Code Playgroud)
这将返回树的所有项目,并将它们全部放在集合的根目录中.此时,您的结果集将如下所示:
-- Item1
-- Item2
-- Item3
-- Item4
-- Item5
-- Item2
-- Item3
-- Item5
Run Code Online (Sandbox Code Playgroud)
既然你可能希望你的实体只是分层次地从EF出来,这不是你想要的,对吧?
..然后,排除存在于根级别的后代:
幸运的是,因为模型中有导航属性,所以仍然会填充子实体集合,如上面结果集的图示所示.通过使用循环手动迭代结果集foreach()
,并将这些根项添加到a new List<TreeSet>()
,您现在将拥有一个包含根元素的列表,并且所有后代都已正确嵌套.
如果您的树木变大并且性能受到关注,您可以将返回集ASCENDING排序ParentID
(对Nullable
,对吗?),以便所有根项都是第一个.像以前一样迭代和添加,但是一旦你得到一个非空的,就会从循环中断开.
var subset = query
// execute the query against the DB
.ToList()
// filter out non-root-items
.Where(x => !x.ParentId.HasValue);
Run Code Online (Sandbox Code Playgroud)
现在subset
看起来像这样:
-- Item1
-- Item2
-- Item3
-- Item4
-- Item5
Run Code Online (Sandbox Code Playgroud)
关于克雷格的解决方案:
- 你真的不想使用延迟加载!围绕n + 1查询的必要性而设计的设计将成为主要的性能吸引力.
*********(嗯,公平地说,如果你要允许用户有选择地向下钻取树,那么它可能是合适的.只是不要使用延迟加载来使它们全部运行起来前线!!)- 我从来没有尝试过嵌套的设置,我也不会建议破解EF配置来使这项工作,因为有一个更容易的解决方案.
- 另一个合理的建议是创建一个提供自链接的数据库视图,然后将该视图映射到中间连接/链接/ m2m表.就个人而言,我发现这个解决方案比必要的更复杂,但它可能有它的用途.
当您使用 时Include()
,您要求实体框架将您的查询转换为 SQL。那么想一想:如何编写返回任意深度的树的 SQL 语句?
答:除非您使用数据库服务器的特定层次结构功能(这不是 SQL 标准,但某些服务器支持,例如 SQL Server 2008,但其实体框架提供程序不支持),否则您不会这样做。在 SQL 中处理任意深度的树的常用方法是使用嵌套集模型而不是父 ID 模型。
因此,您可以使用三种方法来解决此问题:
归档时间: |
|
查看次数: |
17717 次 |
最近记录: |