Linq - группировка по нескольким таблицам с несколькими возвратами - PullRequest
0 голосов
/ 03 августа 2011

Используя Linq to Sql, как сгруппировать следующую таблицу (entidadeProdutosFornecedores) и вернуть поля из N таблиц?

Исходный запрос в SQL

SELECT  @NM_VALOR1      = MAX(ProdutosFornecedores.NM_PRECO_REPOSICAO),
                @NM_VALOR2      = MAX(ProdutosFornecedores.ID_MOEDAS_REPOSICAO),
                @ID_IMPOSTOSDESTINOS    = MAX(Fornecedores.ID_IMPOSTOSDESTINOS),
                @ID_IMPOSTOSCONFIG  = MAX(ProdutosFornecedores.ID_IMPOSTOSCONFIG),
                @ID_TABELANCMS      = MAX(ProdutosFornecedores.ID_TABELANCMS),
                @ID_FORNECEDORES    = MAX(Fornecedores.ID_FORNECEDORES),
                @CD_UF_BASE     = MAX(UnidadesFederacao.CD_UNIDADEFEDERACAO)
              FROM  ProdutosFornecedores
                INNER JOIN Fornecedores     ON Fornecedores.ID_FORNECEDORES       = ProdutosFornecedores.ID_FORNECEDORES
                INNER JOIN Municipios       ON Municipios.ID_MUNICIPIOS       = Fornecedores.ID_MUNICIPIOS
                INNER JOIN UnidadesFederacao    ON UnidadesFederacao.ID_UNIDADESFEDERACAO = Municipios.ID_UNIDADESFEDERACAO
             WHERE  ProdutosFornecedores.ID_PRODUTOS        = CAST(@CD_OBJETO1 AS INT)  AND
                ProdutosFornecedores.ID_PRODUTOSCONFIGPRECOS    = CAST(@CD_OBJETO2 AS INT)  AND
                ProdutosFornecedores.FG_STATUS          = 1
            GROUP BY
                ProdutosFornecedores.ID_PRODUTOS,
                ProdutosFornecedores.ID_PRODUTOSCONFIGPRECOS

Запрос, преобразованный в Linq

var prodForn2 = from entidadeProdutosFornecedores in ERPDAOManager.GetTable<ProdutosFornecedores>()
                                                    //Inner Join with Fornecedores
                                                    join entidadeFornecedores in ERPDAOManager.GetTable<Fornecedores>()
                                                         on entidadeProdutosFornecedores.ID_FORNECEDORES equals entidadeFornecedores.ID into tempFornecedores
                                                    from fornecedores in tempFornecedores
                                                    //Inner Join with Municipios
                                                    join entidadeMuncipios in ERPDAOManager.GetTable<Municipios>()
                                                        on fornecedores.ID_MUNICIPIOS equals entidadeMuncipios.ID into tempMunicipios
                                                    from municipios in tempMunicipios
                                                    //Inner Join with UnidadesFederacao
                                                    join entidadeUnidadesFederacao in ERPDAOManager.GetTable<UnidadesFederacao>()
                                                        on municipios.ID_UNIDADESFEDERACAO equals entidadeUnidadesFederacao.ID into tempUnidadesFederacao
                                                    from unidadesFederacao in tempUnidadesFederacao
                                                    //Filters
                                                    where entidadeProdutosFornecedores.ID_PRODUTOS == Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO1) &&
                                                          entidadeProdutosFornecedores.ID_PRODUTOSCONFIGPRECOS == Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO2) &&
                                                          entidadeProdutosFornecedores.FG_STATUS == true
                                                    group entidadeProdutosFornecedores by new { entidadeProdutosFornecedores.ID_PRODUTOS, entidadeProdutosFornecedores.ID_PRODUTOSCONFIGPRECOS } into produtosFornecedores
                                                    select new
                                                    {
                                                        NM_PRECO_REPOSICAO = (decimal)produtosFornecedores.Max(item => item.NM_PRECO_REPOSICAO),
                                                        ID_MOEDAS_REPOSICAO = (int)produtosFornecedores.Max(item => item.ID_MOEDAS_REPOSICAO),
                                                        ID_IMPOSTOSDESTINOS = (int)fornecedores.ID_IMPOSTOSDESTINOS, //Error: The name fornecedores does not exist in the current context
                                                        ID_IMPOSTOSCONFIG = (int)produtosFornecedores.Max(item => item.ID_IMPOSTOSCONFIG),
                                                        ID_TABELANCMS = (int)produtosFornecedores.Max(item => item.ID_TABELANCMS),
                                                        ID_FORNECEDORES = (int)fornecedores.ID, //Error: The name fornecedores does not exist in the current context
                                                        CD_UF_BASE = (string)unidadesFederacao.CD_UNIDADEFEDERACAO //Error: The name unidadesFederacao does not exist in the current context
                                                    };

Ответы [ 2 ]

3 голосов
/ 04 августа 2011

Проблема, с которой вы сталкиваетесь при запросе, заключается в том, что вы пытаетесь получить доступ к переменным «from» после «group by», чего вы не можете сделать. Чтобы получить эти переменные, они должны либо (1) храниться вне группировки, либо (2) быть частью самой группировки.

(1)

var prodForn2 =
    from produtosFornecedores in ERPDAOManager.GetTable<ProdutosFornecedores>()
    join fornecedores in ERPDAOManager.GetTable<Fornecedores>()
        on produtosFornecedores.ID_FORNECEDORES equals fornecedores.ID
    join municipios in ERPDAOManager.GetTable<Municipios>()
        on fornecedores.ID_MUNICIPIOS equals municipios.ID
    join unidadesFederacao in ERPDAOManager.GetTable<UnidadesFederacao>()
        on municipios.ID_UNIDADESFEDERACAO equals unidadesFederacao.ID
    where produtosFornecedores.ID_PRODUTOS ==
        Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO1)
    where produtosFornecedores.ID_PRODUTOSCONFIGPRECOS ==
        Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO2)
    where produtosFornecedores.FG_STATUS == true
    let ID_IMPOSTOSDESTINOS = (int)fornecedores.ID_IMPOSTOSDESTINOS
    let ID_FORNECEDORES = (int)fornecedores.ID
    let CD_UF_BASE = (string)unidadesFederacao.CD_UNIDADEFEDERACAO
    group produtosFornecedores by new
    {
        ID_IMPOSTOSDESTINOS,
        ID_FORNECEDORES,
        CD_UF_BASE,
    } into gpfs1
    select new
    {
        gpfs1.Key.ID_IMPOSTOSDESTINOS,
        gpfs1.Key.ID_FORNECEDORES,
        gpfs1.Key.CD_UF_BASE,
        PRODUTOSFORNECEDORES =
            from pfs1 in gpfs1
            group pfs1 by new
            {
                pfs1.ID_PRODUTOS,
                pfs1.ID_PRODUTOSCONFIGPRECOS
            } into gpfs2
            select new
            {
                NM_PRECO_REPOSICAO = (decimal)gpfs2
                    .Max(item => item.NM_PRECO_REPOSICAO),
                ID_MOEDAS_REPOSICAO = (int)gpfs2
                    .Max(item => item.ID_MOEDAS_REPOSICAO),
                ID_IMPOSTOSCONFIG = (int)gpfs2
                    .Max(item => item.ID_IMPOSTOSCONFIG),
                ID_TABELANCMS = (int)gpfs2
                    .Max(item => item.ID_TABELANCMS),
            },
    };

(2)

var prodForn2 =
    from produtosFornecedores in ERPDAOManager.GetTable<ProdutosFornecedores>()
    join fornecedores in ERPDAOManager.GetTable<Fornecedores>()
        on produtosFornecedores.ID_FORNECEDORES equals fornecedores.ID
    join municipios in ERPDAOManager.GetTable<Municipios>()
        on fornecedores.ID_MUNICIPIOS equals municipios.ID
    join unidadesFederacao in ERPDAOManager.GetTable<UnidadesFederacao>()
        on municipios.ID_UNIDADESFEDERACAO equals unidadesFederacao.ID
    where produtosFornecedores.ID_PRODUTOS ==
        Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO1)
    where produtosFornecedores.ID_PRODUTOSCONFIGPRECOS ==
        Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO2)
    where produtosFornecedores.FG_STATUS == true
    let ID_IMPOSTOSDESTINOS = (int)fornecedores.ID_IMPOSTOSDESTINOS
    let ID_FORNECEDORES = (int)fornecedores.ID
    let CD_UF_BASE = (string)unidadesFederacao.CD_UNIDADEFEDERACAO
    group produtosFornecedores by new
    {
        ID_IMPOSTOSDESTINOS,
        ID_FORNECEDORES,
        CD_UF_BASE,
        produtosFornecedores.ID_PRODUTOS,
        produtosFornecedores.ID_PRODUTOSCONFIGPRECOS,
    } into gpfs
    select new
    {
        gpfs.Key.ID_IMPOSTOSDESTINOS,
        gpfs.Key.ID_FORNECEDORES,
        gpfs.Key.CD_UF_BASE,
        NM_PRECO_REPOSICAO = (decimal)gpfs.Max(item => item.NM_PRECO_REPOSICAO),
        ID_MOEDAS_REPOSICAO = (int)gpfs.Max(item => item.ID_MOEDAS_REPOSICAO),
        ID_IMPOSTOSCONFIG = (int)gpfs.Max(item => item.ID_IMPOSTOSCONFIG),
        ID_TABELANCMS = (int)gpfs.Max(item => item.ID_TABELANCMS),
    };

Дайте каждому из них попробовать и посмотреть, что лучше соответствует вашим потребностям.

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

var prodForn2_1 =
    from produtosFornecedores in ERPDAOManager.GetTable<ProdutosFornecedores>()
    join fornecedores in ERPDAOManager.GetTable<Fornecedores>()
        on produtosFornecedores.ID_FORNECEDORES equals fornecedores.ID
    join municipios in ERPDAOManager.GetTable<Municipios>()
        on fornecedores.ID_MUNICIPIOS equals municipios.ID
    join unidadesFederacao in ERPDAOManager.GetTable<UnidadesFederacao>()
        on municipios.ID_UNIDADESFEDERACAO equals unidadesFederacao.ID
    where produtosFornecedores.ID_PRODUTOS ==
        Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO1)
    where produtosFornecedores.ID_PRODUTOSCONFIGPRECOS ==
        Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO2)
    where produtosFornecedores.FG_STATUS == true
    let ID_IMPOSTOSDESTINOS = (int)fornecedores.ID_IMPOSTOSDESTINOS
    let ID_FORNECEDORES = (int)fornecedores.ID
    let CD_UF_BASE = (string)unidadesFederacao.CD_UNIDADEFEDERACAO
    select new
    {
        ID_IMPOSTOSDESTINOS = (int)fornecedores.ID_IMPOSTOSDESTINOS,
        ID_FORNECEDORES = (int)fornecedores.ID,
        CD_UF_BASE = (string)unidadesFederacao.CD_UNIDADEFEDERACAO,
        ID_PRODUTOS = produtosFornecedores.ID_PRODUTOS,
        ID_PRODUTOSCONFIGPRECOS = produtosFornecedores.ID_PRODUTOSCONFIGPRECOS,
        NM_PRECO_REPOSICAO = (decimal)produtosFornecedores.NM_PRECO_REPOSICAO,
        ID_MOEDAS_REPOSICAO = (int)produtosFornecedores.ID_MOEDAS_REPOSICAO,
        ID_IMPOSTOSCONFIG = (int)produtosFornecedores.ID_IMPOSTOSCONFIG,
        ID_TABELANCMS = (int)produtosFornecedores.ID_TABELANCMS,
    };

var prodForn2_2 =
    from pf in prodForn2_1.ToArray()
    group ...

Теперь вам просто нужно заполнить prodForn2_2 любым из вариантов (1) или (2) сверху. Обратите внимание, что вызов ToArray заставит выполнить запрос prodForn2_1 и перенести записи в память в виде массива - тогда группировка и подзапрос происходит молниеносно. Вам просто нужно следить за использованием памяти, а не за временем выполнения запроса.

Надеюсь, это поможет.

0 голосов
/ 04 августа 2011

Я решил использовать таким образом:

var prodForn = from produtosFornecedores in ERPDAOManager.GetTable<ProdutosFornecedores>()
                                                   //Inner Join com Fornecedores
                                                   join fornecedores in ERPDAOManager.GetTable<Fornecedores>()
                                                        on produtosFornecedores.ID_FORNECEDORES equals fornecedores.ID
                                                   //Inner Join com Municipios
                                                   join municipios in ERPDAOManager.GetTable<Municipios>()
                                                       on fornecedores.ID_MUNICIPIOS equals municipios.ID
                                                   //Inner Join com UnidadesFederacao
                                                   join unidadesFederacao in ERPDAOManager.GetTable<UnidadesFederacao>()
                                                       on municipios.ID_UNIDADESFEDERACAO equals unidadesFederacao.ID
                                                   //Filtros
                                                   where produtosFornecedores.ID_PRODUTOS == Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO1) &&
                                                         produtosFornecedores.ID_PRODUTOSCONFIGPRECOS == Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO2) &&
                                                         produtosFornecedores.FG_STATUS == true
                                                   group produtosFornecedores by new
                                                   {
                                                       ID_IMPOSTOSDESTINOS = fornecedores.ID_IMPOSTOSDESTINOS,
                                                       ID_FORNECEDORES = fornecedores.ID,
                                                       CD_UF_BASE = unidadesFederacao.CD_UNIDADEFEDERACAO,
                                                       produtosFornecedores.ID_PRODUTOS,
                                                       produtosFornecedores.ID_PRODUTOSCONFIGPRECOS
                                                   } into grpProdutosFornecedores
                                                   select new
                                                   {
                                                       grpProdutosFornecedores.Key.ID_IMPOSTOSDESTINOS,
                                                       grpProdutosFornecedores.Key.ID_FORNECEDORES,
                                                       grpProdutosFornecedores.Key.CD_UF_BASE,
                                                       NM_PRECO_REPOSICAO = (decimal)grpProdutosFornecedores.Max(item => item.NM_PRECO_REPOSICAO),
                                                       ID_MOEDAS_REPOSICAO = (int)grpProdutosFornecedores.Max(item => item.ID_MOEDAS_REPOSICAO),
                                                       ID_IMPOSTOSCONFIG = (int)grpProdutosFornecedores.Max(item => item.ID_IMPOSTOSCONFIG),
                                                       ID_TABELANCMS = (int)grpProdutosFornecedores.Max(item => item.ID_TABELANCMS)
                                                   };

                                    if (prodForn.Count() > 0)
                                    {
                                        NM_VALOR1 = prodForn.First().NM_PRECO_REPOSICAO;
                                        NM_VALOR2 = prodForn.First().ID_MOEDAS_REPOSICAO;
                                        ID_IMPOSTOSDESTINOS = prodForn.First().ID_IMPOSTOSDESTINOS;
                                        ID_IMPOSTOSCONFIG = prodForn.First().ID_IMPOSTOSCONFIG;
                                        ID_TABELANCMS = prodForn.First().ID_TABELANCMS;
                                        ID_FORNECEDORES = prodForn.First().ID_FORNECEDORES;
                                        CD_UF_BASE = prodForn.First().CD_UF_BASE;
                                    }
...