gpt4 book ai didi

entity-framework - Entity Framework - 热切加载两个多对多关系

转载 作者:行者123 更新时间:2023-12-04 18:08:22 26 4
gpt4 key购买 nike

抱歉这么久,但至少我认为我获得了所有信息以便能够理解并可能提供帮助?

我想使用预先加载从我的数据库加载数据。

数据设置了五个表,设置了两个Levels的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(将此处不相关的其他数据 Hook )。

在这三个数据表之间是两个 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 数据结构的一部分。我让 Entity Framework 从这个数据库中构建它的对象,并按照表的方式设置类。
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 表,而不是中间数据表“方式”。

如果我像这样修改行,这不会改变:
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 信息,但不是来自节点的信息(纬度/经度)。如果我访问这些值之一,我会触发另一次访问数据库以加载一个单节点对象。

最后一次旅行是致命的,因为我想加载 1 个关系 -> 300 种方式,每种方式 -> 2000 个节点。所以最后我打到了服务器 1 + 300 + 300*2000 ......我认为还有改进的余地。

但是如何?我无法用有效的语法和急切加载编写最后一条语句。
不感兴趣;有没有办法在一次旅行中加载整个对象图,从一个关系开始?

最佳答案

在一次往返中加载整个图形将是:

IQueryable<relation> query = context.relations;
query = query.Where( ... ); // filters down to exactly one
query = query.Include(r => r.relation_members
.Select(rm => rm.way.way_nodes
.Select(wn => wn.node)));
relation rel = query.SingleOrDefault();

不过,既然你说 Include高达 ...Select(rm => rm.way)没有用,这不太可能奏效。 (如果它可以工作,由于生成的 SQL 的复杂性以及此查询将返回的数据和实体的数量,性能可能并不好笑。)

您应该进一步调查的第一件事是为什么 .Include(r => r.relation_members.Select(rm => rm.way))不起作用,因为它似乎是正确的。您的模型和到数据库的映射是否正确?

通过显式加载获取节点的循环应如下所示:
foreach (relation_member rm in rel.relation_members) {
context.Entry(rm).Reference(r => r.way).Query()
.Include(w => w.way_nodes.Select(wn => wn.node))
.Load();
}

关于entity-framework - Entity Framework - 热切加载两个多对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21065177/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com