Linq -组由多个表与多个返回

本文关键字:返回 -组 Linq | 更新日期: 2023-09-27 18:04:38

使用Linq to Sql如何将以下表(entidadeproductofornecedores)分组并从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
                                                    };

Linq -组由多个表与多个返回

您的查询得到的问题是,您正试图访问"从"变量之后的"组",你不能这样做。为了获得这些变量,它们必须要么(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),
    };

每个都试一试,看看哪个更适合你的需要。

您可能还会发现性能是分组和多个max查询的问题,因此在分组结果之前将记录放入内存可能是值得的。

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 ...

现在您只需要用上面的选项(1)或(2)中的任何一个完成prodForn2_2。注意,ToArray调用将强制执行prodForn2_1查询,并将记录作为一个数组放入内存中——分组和子查询的速度很快。你只需要注意内存的使用而不是查询的执行时间。

我用这种方法解决了使用问题:

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;
                                    }