EF6生成的查询垃圾:消除多余的空检查

时间:2017-05-08 20:25:55

标签: c# mysql entity-framework

  

注意:这是基于[ 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等效检查。这是一个很长的镜头,但我从来不需要明确设置属性,所以不确定它会做什么。

1 个答案:

答案 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`)