• Entity Framework做IN查询


    开发中遇到的Too high level of nesting for select错误

    项目使用了Entity Framework结合Mysql, 遇到了一个非常奇怪的性能问题,一个看起来非常简单的查询通过不了。

    报出错误, “Too high level of nesting for select”。

    整个查询非常简单,只是从表中取到属于一个集合中的id的数据, 比如从表中取到OfficeId 是1, 2,3,6的数据。

    Expression<Func<office, bool>> filter = office => officeIds.Any(id => id == office.OfficeID);
    var offices = _officeRepository.GetOffices(filter).ToList();

    开始一直认为是Mysql的问题,是不是因为Id太多, mysql性能不好,后来发现问题出在EF的使用上。

    实际的查询语句

    后来调试,发现实际执行的sql语句是这样的,而不是我预想的in查询,而是翻译成了非常复杂的查询

    SELECT
    `Extent1`.`OfficeID`,
    `Extent1`.`DoctorPhone`,
    `Extent1`.`Name`,
    `Extent1`.`RegionID`,
    `Extent1`.`PriceTier2`,
    `Extent1`.`PriceTier3`,
    `Extent1`.`PracticeManagementSoftware`,
    `Extent1`.`ServerHost`,
    `Extent1`.`ServerLogin`,
    FROM `office` AS `Extent1`
    WHERE EXISTS(SELECT
    1 AS `C1`
    FROM (SELECT `UnionAll31`.`C1` FROM (SELECT `UnionAll30`.`C1` FROM (SELECT `UnionAll29`.`C1` FROM 
    (SELECT `UnionAll28`.`C1` FROM (SELECT `UnionAll27`.`C1` FROM (SELECT `UnionAll26`.`C1` FROM (SELECT `UnionAll25`.`C1` FROM
    (SELECT `UnionAll24`.`C1` FROM (SELECT `UnionAll23`.`C1` FROM (SELECT `UnionAll22`.`C1` FROM (SELECT `UnionAll21`.`C1` FROM
    (SELECT `UnionAll20`.`C1` FROM (SELECT `UnionAll19`.`C1` FROM (SELECT `UnionAll18`.`C1` FROM (SELECT `UnionAll17`.`C1` FROM
    (SELECT `UnionAll16`.`C1` FROM (SELECT `UnionAll15`.`C1` FROM (SELECT `UnionAll14`.`C1` FROM (SELECT `UnionAll13`.`C1` FROM
    (SELECT `UnionAll12`.`C1` FROM (SELECT `UnionAll11`.`C1` FROM (SELECT `UnionAll10`.`C1` FROM (SELECT `UnionAll9`.`C1` FROM
    (SELECT `UnionAll8`.`C1` FROM (SELECT `UnionAll7`.`C1` FROM (SELECT `UnionAll6`.`C1` FROM (SELECT `UnionAll5`.`C1` FROM
    (SELECT `UnionAll4`.`C1` FROM (SELECT `UnionAll3`.`C1` FROM (SELECT `UnionAll2`.`C1` FROM (SELECT `UnionAll1`.`C1` FROM
    (SELECT 69 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable1` UNION ALL SELECT 20 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable2`) AS `UnionAll1`
    UNION ALL SELECT 55 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable3`) AS `UnionAll2` UNION ALL SELECT 67 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable4`)
    AS `UnionAll3` UNION ALL SELECT 9 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable5`) AS `UnionAll4` UNION ALL SELECT 51 AS `C1` FROM
    (SELECT 1 AS `X`) AS `SingleRowTable6`) AS `UnionAll5` UNION ALL SELECT 59 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable7`) AS `UnionAll6` UNION ALL
    SELECT 18 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable8`) AS `UnionAll7` UNION ALL SELECT 19 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable9`) AS `UnionAll8`
    UNION ALL SELECT 8 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable10`) AS `UnionAll9` UNION ALL SELECT 17 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable11`) AS `UnionAll10`
    UNION ALL SELECT 44 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable12`) AS `UnionAll11` UNION ALL SELECT 4 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable13`) AS `UnionAll12`
    UNION ALL SELECT 3 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable14`) AS `UnionAll13` UNION ALL SELECT 58 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable15`) AS `UnionAll14`
    UNION ALL SELECT 56 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable16`) AS `UnionAll15` UNION ALL SELECT 57 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable17`) AS `UnionAll16`
    UNION ALL SELECT 52 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable18`) AS `UnionAll17` UNION ALL SELECT 29 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable19`) AS `UnionAll18`
    UNION ALL SELECT 64 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable20`) AS `UnionAll19` UNION ALL SELECT 48 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable21`) AS `UnionAll20`
    UNION ALL SELECT 15 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable22`) AS `UnionAll21` UNION ALL SELECT 65 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable23`) AS `UnionAll22`
    UNION ALL SELECT 61 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable24`) AS `UnionAll23` UNION ALL SELECT 50 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable25`) AS `UnionAll24`
    UNION ALL SELECT 62 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable26`) AS `UnionAll25` UNION ALL SELECT 16 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable27`) AS `UnionAll26`
    UNION ALL SELECT 68 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable28`) AS `UnionAll27` UNION ALL SELECT 49 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable29`) AS `UnionAll28`
    UNION ALL SELECT 12 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable30`) AS `UnionAll29` UNION ALL SELECT 11 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable31`) AS `UnionAll30`
    UNION ALL SELECT 7 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable32`) AS `UnionAll31` UNION ALL SELECT 5 AS `C1` FROM (SELECT 1 AS `X`) AS `SingleRowTable33`) AS `UnionAll32` WHERE (`UnionAll32`.`C1`) = `Extent1`.`OfficeID`)

    修改成IN查询

    修改后的代码是,

    Expression<Func<office, bool>> filter = office => officeIds.Contains(office.OfficeID);
    var offices = _officeRepository.GetOffices(filter).ToList();

    只是将Any方法,替换成了Contains, EF就正确的翻译成想要的IN查询了:

    SELECT
    `Extent1`.`OfficeID`,
    `Extent1`.`DoctorPhone`,
    `Extent1`.`Name`,
    `Extent1`.`RegionID`,
    `Extent1`.`IsActive`,
    `Extent1`.`IsDeleted`,
    `Extent1`.`InsuranceOnly`,
    `Extent1`.`MinimumFlatRate`,
    FROM `office` AS `Extent1`
    WHERE `Extent1`.`OfficeID` IN ( 69,20,55,67,9,51,59,18,19,8,17,44,4,3,58,56,57,52,29,64,48,15,65,61,50,62,16,68,49,12,11,7,5 ) 

    到这里,问题已经解决了,看来EF中的一些细节还需要自己不断地学习和实践。

  • 相关阅读:
    模板方法模式
    策略模式
    代理模式
    单例模式
    工厂模式
    服务器负载过高问题分析
    支付宝APP支付开发- IOException : DerInputStream.getLength(): lengthTag=89, too big
    阿里云linux服务器挂载数据盘
    3.3.4.2选择特定行
    3.3.4.1选择所有数据
  • 原文地址:https://www.cnblogs.com/JustRun1983/p/3321025.html
Copyright © 2020-2023  润新知