注意:这是基于[ MySQL ]
构建的
假设我有一个master =>详细结构,用以下Linq查询表示:
IQueryable query = from master in myschema_master
join detail in myschema_detail
on detail.correlator equals request.id
select new
{
Id = master.id,
Attribute = detail.interestingcolumn
}
如果我直接对数据库执行以下查询,我的~2M记录集开始在~2秒内返回
(注意:这不是EF Provider为上述语句发送到数据库的查询)
select *
from myschema_master
inner join myschema_detail
on myschema_master.id = myschema_detail.correlator
假设我希望Entity Framework将^发送到数据库。 如何防止它将此垃圾发送到我的内部联接的末尾:
OR ((`Extent1`.`correlator` IS NULL) AND (`Extent2`.`id` IS NULL))
对于上下文,提供程序发送到数据库的完整查询是:
SELECT
1 AS `C1`,
`Extent1`.`id`,
`Extent2`.`interestingattribute`
FROM `myschema_master` AS `Extent1`
INNER JOIN `myschema_detail` AS `Extent2`
ON ((`Extent1`.`id`) = `Extent2`.`correlator`)
OR (
(`Extent1`.`id` IS NULL)
AND (`Extent2`.`correlator` IS NULL)
)
Alsøwik:id和correlator字段可以为Intul并且当前无法修改,但我想完全消除EF和底层提供程序发送到db的空检查。 (master.id为null且detail.correlator为null)创建一个无用的笛卡尔积,只会浪费处理时间
Alsøalsøwik ...我尝试将Configuration.UseDatabaseNullSemantics设置为true和false(在单独的往返行程中,明智的人),并且都没有删除IS NULL等效检查。这是一个很长的镜头,但我从来不需要明确设置属性,所以不确定它会做什么。
答案 0 :(得分:0)
功能改变的解决方案
我可以为此设计的第一个可行解决方案是消除查询中的连接条件并将过滤推送到哪里。这导致以下Linq查询。
IQueryable query = from master in myschema_master
join detail in myschema_detail
on 1 equals 1
where detail.correlator == (Int64?)master.id
select new
{
Id = master.id,
Attribute = detail.interestingcolumn
};
//In LinqPad
(this as IObjectContextAdapter).ObjectContext.CommandTimeout = 120;
this.Configuration.UseDatabaseNullSemantics = true;
var set = query.Dump();
//Outside of LinqPad, just set ^ on Context and materialize the
//IEnumerable as you normally would
结果SQL是
SELECT
1 AS `C1`,
`Extent1`.`id`,
`Extent2`.`interestingcolumn`
FROM `my_schema_master` AS `Extent1`
INNER JOIN `myschema_detail` AS `Extent2` ON 1 = 1
WHERE `Extent2`.`correlator` = (`Extent1`.`id`)