gpt4 book ai didi

c# - 使用 join 进行预加载

转载 作者:太空狗 更新时间:2023-10-30 00:50:14 24 4
gpt4 key购买 nike

我有一个连接两个表的查询,这两个表在 Entity Framework 中没有定义的关系,并且连接的表具有到第三个表的一对多导航属性。

msg 和 job 之间存在一对多关系,但没有外键,也没有在 .EDMX 中定义关联。

job和lock是一对多的关系,在.EDMX中定义了一个关联,所以job有一个job.locks导航属性m,lock有一个lock.job导航属性。

我的原始查询:

var msgsAndJobs = (
from m in dbContext.msgs
join j in dbContext.jobs
on new { jobid = m.jobid, priority = m.priority }
equals new { jobid = j.jobid, priority = j.priority }
where m.msgtype == "EMERGENCY"
orderby new { m.recvdt }
select new { m, j }
);

我发现 EF 正在为联接生成一个查询,然后执行第二个查询以填充联接返回的每条记录的导航属性。

Microsoft 的文档解释了这个问题:https://msdn.microsoft.com/en-us/data/jj574232.aspx

所以我认为我可以使用 .Include() 子句来急切加载所涉及的记录。但它似乎不起作用:

我的新查询:

var msgsAndJobs = (
from m in dbContext.msgs
join j in dbContext.jobs.Include("locks")
on new { jobid = m.jobid, priority = m.priority }
equals new { jobid = j.jobid, priority = j.priority }
where m.msgtype == "EMERGENCY"
orderby new { m.recvdt }
select new { m, j }
);

而且它仍在为每个作业锁生成一个查询。

知道我做错了什么吗?

最佳答案

这就是 Include 的问题。让它失效太容易了,而且它为什么不起作用并不总是很清楚。破坏 Include 的一件事是 changing the shape of the query .另一个是 projecting to a non-entity type or an anonymous type .

这似乎使得预测 Include 何时起作用和不起作用变得异常困难,但有一个简单的技巧:Include 总是起作用,如果你在查询结束时应用它。

如果你不能在那里应用它,它无论如何都不会有效。

考虑到这一点,如果我们查看您的案例,就会很清楚为什么 Include 不起作用。你做不到

(... select new { m, j }).Include("locks"); // Runtime error

因为 locks 显然不是匿名类型的导航属性。如果您使用 lambda 版本,则更明显:

(... select new { m, j }).Include(x => x.locks); // Doesn't compile

所以你的Include是无效的,locks是按需加载的。

幸运的是,由于关系修复,EF 可以通过实体的导航属性将上下文中的实体编织在一起。将您的查询更改为:

var msgsAndJobs = (
from m in dbContext.msgs
join j in dbContext.jobs
on new { jobid = m.jobid, priority = m.priority }
equals new { jobid = j.jobid, priority = j.priority }
where m.msgtype == "EMERGENCY"
orderby new { m.recvdt }
select new { m, j, j.locks }
).AsEnumerable()
.Select(x => new { x.m, x.j });

如果您执行此查询,.AsEnumerable() 会将结果加载到上下文中,之后您可以选择您最初想要的结果。现在您会注意到 EF 已填充所有 job.locks 集合。

但有一件重要的事情:您必须禁用延迟加载,否则处理 job.locks 集合仍会触发延迟加载。这是因为,即使集合已填充,它也未在内部标记为 Loaded

关于c# - 使用 join 进行预加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32955623/

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