簡體   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