Entity Framework Core 是否支持使用 NPGSQL 进行字符串聚合?

问题描述 投票:0回答:1

我正在尝试使用 Npgsql 将此 PostgreSQL 查询转换为 Linq:

var result = _dbContext.Substrates.FromSql(@$"SELECT 
                                                vs.*,
                                                STRING_AGG(DISTINCT p.product_ref, ', ') AS product_ref,
                                                STRING_AGG(DISTINCT cu.acr, ', ') AS acr
                                            FROM 
                                                portal_data.v_substrates vs
                                            LEFT JOIN portal_data.custart c ON c.article_id = vs.id_substrate
                                            LEFT JOIN portal_data.product_components pc ON pc.id_component = vs.id_substrate
                                            LEFT JOIN portal_data.products p ON p.id_product = pc.id_product
                                            LEFT JOIN portal_data.customers cu ON cu.id_customer = c.id_customer
                                            WHERE
                                                c.id_customer = {customerId}
                                            GROUP BY
                                                vs.id_substrate,
                                                vs.substrate_type,
                                                vs.substrate_creation_date,
                                                vs.substrate_status,
                                                vs.substrate_invent_qty,
                                                vs.record_copy_date,
                                                vs.mapped_status
                                            ");

根据 Npgsql 文档,有一个名为

EF.Functions.StringToArray()
的翻译函数,如果我理解正确的话,它会翻译为
string_agg(s, '|')

var substrates = from substrate in _dbContext.Substrates
                 join custart in _dbContext.CustomerArticles on substrate.IdSubstrate equals custart.ArticleId
                 join component in _dbContext.ProductComponents on substrate.IdSubstrate equals component.IdComponent
                 join product in _dbContext.Products on component.IdProduct equals product.IdProduct
                 join customer in _dbContext.Customers on custart.IdCustomer equals customer.Id                              
                 where custart.IdCustomer == customerId
                 select new SubstrateExtended
                 {
                     IdSubstrate = substrate.IdSubstrate,
                     SubstrateType = substrate.SubstrateType,
                     SubstrateCreationDate = substrate.SubstrateCreationDate,
                     SubstrateStatus = substrate.SubstrateStatus,
                     SubstrateInvetoryQuantity = substrate.SubstrateInvetoryQuantity,
                     RecordCopyDate = substrate.RecordCopyDate,
                     MappedStatus = substrate.MappedStatus,
                     ProductRef = EF.Functions.StringToArray(product.ProductRef, ", "),
                     Acr = EF.Functions.StringToArray(customer.Accronym, ", ")
                 };

但这不起作用,因为

EF.Functions.StringToArray()
返回一个
string[]

有没有办法将 SQL 查询转换为 Linq,而无需检索用于聚合的完整项目列表?

c# .net postgresql entity-framework-core npgsql
1个回答
0
投票

等价的是

string.Join
,其中第二个参数是
IEnumerable<string>

但是您还缺少

group by
,并且原始查询中的连接是
left join

var substrates =
    from substrate in _dbContext.Substrates
    join custart1 in _dbContext.CustomerArticles on substrate.IdSubstrate equals custart.ArticleId into j1 from custart in j1.DefaultIfEmpty()
    join component1 in _dbContext.ProductComponents on substrate.IdSubstrate equals component.IdComponent into j2 from component in j2.DefaultIfEmpty()
    join product1 in _dbContext.Products on component.IdProduct equals product.IdProduct into j3 from product in j3.DefaultIfEmpty()
    join customer1 in _dbContext.Customers on custart.IdCustomer equals customer.Id into j4 from customer in j4.DefaultIfEmpty()
    where custart.IdCustomer == customerId
    group new { custart, component, product, customer } by substrate into g
    select new SubstrateExtended
    {
        IdSubstrate = substrate.IdSubstrate,
        SubstrateType = substrate.SubstrateType,
        SubstrateCreationDate = substrate.SubstrateCreationDate,
        SubstrateStatus = substrate.SubstrateStatus,
        SubstrateInvetoryQuantity = substrate.SubstrateInvetoryQuantity,
        RecordCopyDate = substrate.RecordCopyDate,
        MappedStatus = substrate.MappedStatus,
        ProductRef = string.Join(", ", g.Select(t => t.product.ProductRef).Distinct()),
        Acr = string.Join(", ", g.Select(t => t.customer.Accronym).Distinct())
    };

话虽如此,最好重新考虑您的连接并通过使用子查询进行预聚合来删除不同的和分组依据。

var substrates =
    from substrate in _dbContext.Substrates
    where custart.IdCustomer == customerId

    let acr = string.Join(", ",
        from custart in _dbContext.CustomerArticles
        join customer1 in _dbContext.Customers on custart.IdCustomer equals customer.Id
        where substrate.IdSubstrate == custart.ArticleId
        select customer.Accronym
    )

    let productRef = string.Join(", ",
        from component1 in _dbContext.ProductComponents
        join product1 in _dbContext.Products on component.IdProduct equals product.IdProduct
        where substrate.IdSubstrate == component.IdComponent
        select product.ProductRef
    )

    select new SubstrateExtended
    {
        IdSubstrate = substrate.IdSubstrate,
        SubstrateType = substrate.SubstrateType,
        SubstrateCreationDate = substrate.SubstrateCreationDate,
        SubstrateStatus = substrate.SubstrateStatus,
        SubstrateInvetoryQuantity = substrate.SubstrateInvetoryQuantity,
        RecordCopyDate = substrate.RecordCopyDate,
        MappedStatus = substrate.MappedStatus,
        ProductRef = productRef,
        Acr = acr
    };
© www.soinside.com 2019 - 2024. All rights reserved.