Множественное левое соединение, скомпилированное в linq - PullRequest
0 голосов
/ 25 октября 2019

В моем проекте API с EntityFramework я должен перевести следующий оператор SQL

 select p.cod_paquete, p.nombre, a.descripcion, a.proceso, a.color, a.descripcion, (select count(*) from paqueteAcabado where paquete=a.paquete and color=a.color), coalesce(pc.titulo,''), case when pc.opcional=1 then 1 else 0 end as opcional, pa.optativo, a.opcional 
  from paqueteAPP pa 
  inner join paquete p on p.cod_paquete=pa.paquete 
  left join paqueteAcabado a on a.paquete=p.cod_paquete and a.opcional=1 
  left join coste c on c.cod_coste=a.acabado 
  left join paqueteColor pc on pc.paquete=p.cod_paquete and pc.color=a.color 
  where pa.agrupacionProductoProducto= '298'
  order by coalesce(pa.orden,0), p.cod_paquete, a.color, a.descripcion 

Класс

public class SQLResultadoPaquetesAcabado
    {
        public short cod_paquete { get; set; }
        public string nombre { get; set; }
        public string descripcion { get; set; }
        public short proceso { get; set; }
        public string color { get; set; }
        public int? paquetesColor { get; set; }
        public string titulo { get; set; }
        public bool? PaqueteColoropcional { get; set; }
        public bool optativo { get; set; }
        public bool? acabadoOpcional { get; set; }

    }

sqlпереведено на Linq

 int codigo = 298;
 Paquetes = (from paqueteAPP pa in db.paqueteAPP
                    join paquete p in db.paquete on pa.paquete equals p.cod_paquete
                    join paqueteAcabado a in db.paqueteAcabado on p.cod_paquete equals a.paquete into pcacabado
                    from pacabado in pcacabado.DefaultIfEmpty()
                    join coste c in db.coste on pacabado.acabado equals c.cod_coste into pacabadocoste1
                    from pcosteacabado in pacabadocoste1.DefaultIfEmpty()
                    join paqueteColor pc in db.paqueteColor on p.cod_paquete equals pc.paquete into pcolor
                    from pacolor in pcolor.DefaultIfEmpty()
                    where pa.agrupacionProductoProducto == codigo && pacabado.opcional == true
                    select new SQLResultadoPaquetesAcabado
                    {
                        cod_paquete = p.cod_paquete,
                        nombre = p.nombre,
                        descripcion = pacabado.descripcion,
                        proceso = pacabado.proceso,
                        color = pacabado.color,
                        paquetesColor = (from paqueteAcabado pa in db.paqueteAcabado
                                         where pa.paquete == pacabado.paquete && pa.color == 
 pacabado.color
                                         select pa).Count(),

                        titulo = pacolor.titulo,
                        PaqueteColoropcional = pacolor.opcional,
                        optativo = pa.optativo,
                        acabadoOpcional = pacabado.opcional
                    });

SQL, полученный при переводе с Linq на SQL

SELECT COUNT
[Project1].[agrupacionProductoProducto] AS [agrupacionProductoProducto], 
[Project1].[cod_paquete] AS [cod_paquete], 
[Project1].[nombre] AS [nombre], 
[Project1].[descripcion] AS [descripcion], 
[Project1].[proceso] AS [proceso], 
[Project1].[color] AS [color], 
[Project1].[C1] AS [C1], 
[Project1].[titulo] AS [titulo], 
[Project1].[opcional1] AS [opcional], 
[Project1].[optativo] AS [optativo], 
[Project1].[opcional] AS [opcional1]
FROM ( SELECT 
    [Filter1].[agrupacionProductoProducto] AS [agrupacionProductoProducto], 
    [Filter1].[optativo] AS [optativo], 
    [Filter1].[cod_paquete] AS [cod_paquete], 
    [Filter1].[nombre] AS [nombre], 
    [Filter1].[proceso] AS [proceso], 
    [Filter1].[descripcion] AS [descripcion], 
    [Filter1].[opcional] AS [opcional], 
    [Filter1].[color] AS [color], 
    [Extent4].[titulo] AS [titulo], 
    [Extent4].[opcional] AS [opcional1], 
    (SELECT 
        COUNT(1) AS [A1]
        FROM [dbo].[paqueteAcabado] AS [Extent5]
        WHERE ([Extent5].[paquete] = [Filter1].[paquete1]) AND (([Extent5].[color] = [Filter1].[color]) OR (([Extent5].[color] IS NULL) AND ([Filter1].[color] IS NULL)))) AS [C1]
    FROM   (SELECT [Extent1].[agrupacionProductoProducto] AS [agrupacionProductoProducto], [Extent1].[optativo] AS [optativo], [Extent2].[cod_paquete] AS [cod_paquete], [Extent2].[nombre] AS [nombre], [Extent3].[proceso] AS [proceso], [Extent3].[paquete] AS [paquete1], [Extent3].[descripcion] AS [descripcion], [Extent3].[opcional] AS [opcional], [Extent3].[color] AS [color]
        FROM   [dbo].[paqueteAPP] AS [Extent1]
        INNER JOIN [dbo].[paquete] AS [Extent2] ON [Extent1].[paquete] = [Extent2].[cod_paquete]
        INNER JOIN [dbo].[paqueteAcabado] AS [Extent3] ON [Extent2].[cod_paquete] = [Extent3].[paquete]
        WHERE 1 = [Extent3].[opcional] ) AS [Filter1]
    LEFT OUTER JOIN [dbo].[paqueteColor] AS [Extent4] ON [Filter1].[cod_paquete] = [Extent4].[paquete]
    WHERE [Filter1].[agrupacionProductoProducto] = '298'
)  AS [Project1]

Моя проблема в том, что SQLсостоит из трех левых объединений

И с помощью linq я могу создать только одно левое объединение, как вы можете видеть в результате генерации linq для sql

SQL

left join paqueteAcabado a on a.paquete=p.cod_paquete and a.opcional=1 
left join coste c on c.cod_coste=a.acabado 
left join paqueteColor pc on pc.paquete=p.cod_paquete and pc.color=a.color 

Linq

INNER JOIN [dbo].[paquete] AS [Extent2] ON [Extent1].[paquete] = [Extent2].[cod_paquete]
        INNER JOIN [dbo].[paqueteAcabado] AS [Extent3] ON [Extent2].[cod_paquete] = [Extent3].[paquete]
        WHERE 1 = [Extent3].[opcional] ) AS [Filter1]
    LEFT OUTER JOIN [dbo].[paqueteColor] AS [Extent4] ON [Filter1].[cod_paquete] = [Extent4].[paquete]

Мой вопрос заключается в том, как успешно воспроизвести SQL с помощью linq без использования отдельного? Потому что с отличным, я получаю результат, который я хочу, но я получаю 120 повторяющихся строк, которые я не хочу

1 Ответ

0 голосов
/ 25 октября 2019

Я работаю со своим собственным кодом, но преобразование кода очень сложно. Тем не менее, я пытаюсь объяснить, как создавать левые внешние объединения, такие как SQL-запросы.

Имейте в виду, что это не окончательный запрос. Вы должны добавить внутренние запросы (я думаю, что вы могли бы), и если вы получаете ключевые слова соединения, не соответствующие исключению, вы должны добавить те же имена.

Теперь код здесь, я пытаюсь преобразовать некоторые части:

var joinTest = context.paqueteAPP.Join(context.paquete,
        pa => pa.paquete,
        p => p.cod_paquete,
        (pa, p) =>
            new {p.cod_paquete, p.nombre,p.cod_paquete})
    .GroupJoin(context.paqueteAcabado,
        a => new
        {
            a.paquete,
            a.opcional
        }, 
        temp => new {paquete=temp.cod_paquete,opcional=1},
        (temp, paqueteAcabado) => new {temp.cod_paquete, temp.nombre, paqueteAcabado})
    .SelectMany(s => s.paqueteAcabado.DefaultIfEmpty(),
        (s, paqueteAcabado) => new {s.cod_paquete, s.nombre,paqueteAcabado.descripcion, paqueteAcabado.proceso, paqueteAcabado.color, paqueteAcabado.descripcion,paqueteAcabado.acabado})
    .GroupJoin(context.coste,
        a => a.acabado, c => c.cod_coste,
        (temp, coste) => new { temp.cod_paquete, temp.nombre,temp.descripcion, temp.proceso, temp.color, temp.descripcion, coste })
    .SelectMany(s => s.coste.DefaultIfEmpty(),
        (s, coste) => new { s.cod_paquete, s.nombre,s.descripcion, s.proceso, s.color, s.descripcion, coste.Name })
    .ToList();

Этот запрос создает 1 внутреннее и 2 левых соединения.

Если вам нужна дополнительная помощь, пожалуйста,добавьте сущности (что вам нужно) и некоторые данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...