很抱歉这么长,但至少我认为我获得了所有信息以便能够理解并可能有所帮助?
我想使用预加载从数据库加载数据。
数据设置在五个表中,设置两个级别的 m:n 关系。因此,存在三个包含数据的表(以从上到下的层次结构方式排序):
CREATE TABLE [dbo].[relations](
[relation_id] [bigint] NOT NULL
)
CREATE TABLE [dbo].[ways](
[way_id] [bigint] NOT NULL
)
CREATE TABLE [dbo].[nodes](
[node_id] [bigint] NOT NULL,
[latitude] [int] NOT NULL,
[longitude] [int] NOT NULL
)
前两个实际上只包含它们自己的 ID(用于挂钩此处不相关的其他数据)。
在这三个数据表之间是两个 m:n 表,带有排序提示:
CREATE TABLE [dbo].[relations_ways](
[relation_id] [bigint] NOT NULL,
[way_id] [bigint] NOT NULL,
[sequence_id] [smallint] NOT NULL
)
CREATE TABLE [dbo].[ways_nodes](
[way_id] [bigint] NOT NULL,
[node_id] [bigint] NOT NULL,
[sequence_id] [smallint] NOT NULL
)
这本质上是 OpenStreetMap 数据结构的一部分。我让实体框架从该数据库构建它的对象,并按照表的形式设置类。
m:n 表确实作为类存在。 (我知道在 EF 中,您可以构建对象 m:n 关系,而无需明确的中间类 - 我应该尝试以这种方式更改对象模型吗?)
我想做的事:我的切入点正是一项关系。
我认为最好首先急切加载中间的 m:n 关系,然后在循环中迭代该关系并急切加载最低的关系。我尝试通过以下方式做到这一点
IQueryable<relation> query = context.relations;
query = query.Where( ... ); // filters down to exactly one
query = query.Include(r => r.relation_members);
relation rel = query.SingleOrDefault();
只需一次访问数据库即可加载关系以及所有 1:n 信息 - 好吧,很好。但我注意到它只加载 1:n 表,而不加载中间数据表“ways”。
如果我像这样修改该行,这不会改变:
query = query.Include(r => r.relation_members.Select(rm => rm.way));
所以我似乎无法在这里加载中间级别?
我根本无法工作的是急切地加载节点级别的数据。我尝试了以下方法:
foreach (relation_member rm in rel.relation_members) {
IQueryable<way_node> query = rm.way.way_nodes.AsQueryable();
query = query.Include(wn => wn.node);
query.Load();
}
这确实有效,并且在每次迭代的一个语句中急切地加载中间级别的方式和 way_node 的所有 1:n 信息,但是not来自节点的信息(纬度/经度)。如果我访问这些值之一,我会触发另一次数据库访问以加载一个单节点对象。
最后一次旅行是致命的,因为我想加载 1 个关系 -> 300 个路径,每个路径 -> 2000 个节点。所以最终我会选择服务器 1 + 300 + 300*2000...我认为还有改进的空间。
但如何呢?我无法用有效的语法和急切加载来编写最后一条语句。
不感兴趣;有没有一种方法可以从一个关系开始一次加载整个对象图?