繁体   English   中英

Npgsql中的重复联接具有相同的导航属性

[英]Duplicated joins in Npgsql for the same navigation property

这个问题已经存在在这里 ,但对于实体框架TSQL

当对一个选择多次使用相同的导航属性时,Npgsql查询会导致多个联接,每次使用导航属性都会产生一个联接。 这会导致性能下降(经过测试)

我已经读到这是EF 4的问题,但是在EF 6上也会发生此问题。

我认为这是Npgsql LINQ to SQL转换器的问题

这是Npgsql为使用多个时间的相同导航属性生成的代码,显然,只需要一个联接(从其他问题复制,因为情况完全相同)

LEFT OUTER JOIN [dbo].[Versions] AS [Extent4] ON [Extent1].[IDVersionReported] = [Extent4].[ID]
LEFT OUTER JOIN [dbo].[Versions] AS [Extent5] ON [Extent1].[IDVersionReported] = [Extent5].[ID]
LEFT OUTER JOIN [dbo].[Versions] AS [Extent6] ON [Extent1].[IDVersionReported] = [Extent6].[ID]
LEFT OUTER JOIN [dbo].[Versions] AS [Extent7] ON [Extent1].[IDVersionReported] = [Extent7].[ID]

是否可以调整PostgreSql以优化重复连接?

如果没有,哪个选项最适合解决此问题?

  • 等待Npgsql修复
  • 下载Npgsql代码并找到解决方法
  • 在到达数据库之前拦截生成的SQL,对其进行解析,然后删除重复的联接。 在这里阅读)
  • 不要使用导航属性,而是使用LINQ联接

确实,这是Entity Framework的问题,但是我找到了一种解决方法,希望这对某人有所帮助。

这是原来where的LINQ查询的一部分:

 from cr in Creditos
 where cr.validado == 1 &&
 cr.fecharegistro >= Desde &&
 cr.fecharegistro <= Hasta &&
 !ProductosExcluidos.Contains(cr.idproducto.Value) &&
 cr.amortizaciones.Sum(am => am.importecapital - am.pagoscap - am.capcancel) > 1

 //All references to the navigation property cr.numcliente
 //results on a separated LEFT OUTTER JOIN between this the 'creditos' and 'clientes' tables
 select new ArchivoCliente
 {
    RFC = cr.numcliente.rfc,
    Nombres = cr.numcliente.nombres,
    ApellidoPaterno = cr.numcliente.apellidopaterno,
    ApellidoMaterno = cr.numcliente.apellidomaterno,
 }

请注意where的最后一个条件,该条件对cr的所有子实体求和,如果我们取出该最后一个条件,则所有重复的LEFT OUTTER JOIN都将被一个JOIN替换,出于某种原因,Entity Framework不会如查询的where部分的子查询或聚合

如果相反,我们用其他等效查询替换了原始查询,则仅生成一个LEFT OUTTER JOIN

 (from cr in Creditos
 where cr.validado == 1 &&
 cr.fecharegistro >= Desde &&
 cr.fecharegistro <= Hasta &&
 !ProductosExcluidos.Contains(cr.idproducto.Value) &&
 //Excluded aggregate function condition from the first where
 //the value is now on the select and used for posterior filtering

 select new ArchivoCliente
 {
    RFC = cr.numcliente.rfc,
    Nombres = cr.numcliente.nombres,
    ApellidoPaterno = cr.numcliente.apellidopaterno,
    ApellidoMaterno = cr.numcliente.apellidomaterno,
    SumaAmort = cr.amortizaciones.Sum(am => am.importecapital - am.pagoscap - am.capcancel)
 }).Where (x => x.SumaAmort > 1);

现在,不是直接对第一个where语句进行过滤,而是将汇总结果存储为投影的一部分,然后将第二个where应用于结果查询。

这将导致查询速度大大提高,只对翻译后的SQL语句进行必要的联接。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM