2015-10-21 1 views
0

Этот вопрос уже существует here, но для Entity Framework для TsqlДублированный присоединяется Npgsql для того же свойства навигации

при использовании той же свойство навигации несколько раз на избранных, результаты запроса Npgsql в нескольких соединений, один для каждого использование навигационного свойства. Этот результат в хите ужасных производительностей (проверено)

Я читал, что это проблема с EF 4, но эта проблема также возникает на EF 6.

Я думаю, что это проблема с Npgsql LINQ к SQL переводчику

Это код, который Npgsql генерировать для того же свойства навигации использовали mutliple раз, очевидно, только один присоединиться к необходимости (копируется из других вопросов, потому что это именно тот самый случай)

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 код и найти способ исправить это
  • Intercept генерируется SQL до достижения базы данных, разобрать его и удалить дубликаты соединений. (Read here)
  • Не используйте навигационные свойства, использовать LINQ присоединяется вместо
+0

Я думаю, что вы правы, это на уровне перевода запросов NPGSQL для EF, хотя я лично этого не заметил. По крайней мере, зарегистрируйте проблему здесь: https://github.com/npgsql/Npgsql/issues. Было бы здорово, если бы вы могли это исправить, но я подозреваю, что это не так. Я думаю, что это, вероятно, хорошее место для начала в коде, вы захотите его построить и присоединить к нему, чтобы вы могли видеть, что происходит. https://github.com/npgsql/npgsql/blob/master/src/EntityFramework6.Npgsql/SqlGenerators/SqlBaseGenerator.cs # L424 –

+0

Команда Npgsql только что закрыла проблему, она швыряет ее на стороне Entity Framework. благодаря – rafael

ответ

0

Действительно, это проблема 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, 
} 

Примечание последнее условие где, что условие делает сумма всех дочерних субъектов cr, если мы примем, что последнее условие, все дублируется LEFT OUTTER JOIN заменены одной JOIN, по какой-то причине, Entity Framework не нравится подзапросы или агрегаты на where частях запроса

Если вместо того, чтобы заменить исходный запрос с этим другим эквивалентным запросом только в качестве ingle 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); 

Теперь вместо того, чтобы непосредственно фильтрации на первой, где утверждение, совокупный результат сохраняется как часть проекции, а затем, второй, когда применяется к полученному запросу.

Это приводит к гораздо более быстрому запросу, при котором необходимы только необходимые соединения в операторе переведенного SQL.