You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

EF Core 8.0.6中如何高效实现订单表按订单号去重后关联客户表并映射为DTO

EF Core 8.0.6中如何高效实现订单表按订单号去重后关联客户表并映射为DTO

嗨,我来给你几个高效又简洁的方案,都是适配EF Core 8.0.6的,完美匹配你的需求——按订单号去重后关联客户表,最终映射成CustomerOrder DTO:

方案一:用DistinctBy实现极简去重(推荐优先用)

EF Core 5及以上版本提供了DistinctBy方法,可以直接指定去重的字段,代码最简洁,生成的SQL效率也很高:

var customerOrders = await _context.Orders
    // 按订单号去重,每个订单号只保留一条记录
    .DistinctBy(o => o.Order_Number)
    // 关联客户表,关联条件是双方的Customer_Key相等
    .Join(
        _context.Customers,
        order => order.Customer_Key,
        customer => customer.Customer_Key,
        // 映射到你的DTO
        (order, customer) => new CustomerOrder
        {
            OrderNumber = order.Order_Number,
            CustomerNumber = customer.Customer_No,
            CustomerName = $"{customer.First_Name} {customer.Last_Name}",
            Address = customer.Address,
            City = customer.City,
            State = customer.State,
            ZipCode = customer.Zip_Code,
            Email = customer.eMail,
            Phone = customer.Phone
            // 补充你需要的其他DTO字段
        })
    .ToListAsync();

这个方案的优势是代码直观,EF Core会帮你生成最优的去重SQL,不需要自己写复杂的分组逻辑,适合只需要简单去重的场景。

方案二:用窗口函数精准控制去重规则(适合有排序需求的场景)

如果你的订单表中,同一个订单号对应的多条记录有先后顺序(比如你想取最新创建的那条),EF Core 8.0对窗口函数的支持非常完善,可以用RowNumber来实现精准去重:

var customerOrders = await _context.Orders
    // 先给每个订单号的记录分配行号,按你需要的规则排序(比如这里用Order_Number,你可以换成创建时间等字段)
    .Select(o => new 
    {
        o.Order_Number,
        o.Customer_Key,
        RowNum = EF.Functions.RowNumber().Over(
            partitionBy: o.Order_Number, 
            orderBy: o.Order_Number) // 这里可以改成 orderBy: o.CreationTime descending 来取最新记录
    })
    // 只保留每个订单号的第一条记录
    .Where(r => r.RowNum == 1)
    // 关联客户表并映射DTO
    .Join(
        _context.Customers,
        r => r.Customer_Key,
        c => c.Customer_Key,
        (r, c) => new CustomerOrder
        {
            OrderNumber = r.Order_Number,
            CustomerNumber = c.Customer_No,
            CustomerName = $"{c.First_Name} {c.Last_Name}",
            Address = c.Address,
            City = c.City,
            State = c.State,
            ZipCode = c.Zip_Code,
            Email = c.eMail,
            Phone = c.Phone
        })
    .ToListAsync();

这种方案适合需要精准控制去重逻辑的场景,比如必须取每个订单号的最新/最早记录,生成的SQL会用窗口函数,性能也很出色。

方案三:用GroupBy分组去重

如果你习惯用分组的方式处理,也可以通过GroupBy按订单号分组,再取每组的第一条记录:

var customerOrders = await _context.Orders
    // 按订单号分组
    .GroupBy(o => o.Order_Number)
    // 取每组的第一条记录(如果需要排序,可以在GroupBy后加OrderBy再取First)
    .Select(g => g.First())
    // 关联客户表并映射DTO
    .Join(
        _context.Customers,
        order => order.Customer_Key,
        customer => customer.Customer_Key,
        (order, customer) => new CustomerOrder
        {
            OrderNumber = order.Order_Number,
            CustomerNumber = customer.Customer_No,
            CustomerName = $"{customer.First_Name} {customer.Last_Name}",
            Address = customer.Address,
            City = customer.City,
            State = customer.State,
            ZipCode = customer.Zip_Code,
            Email = customer.eMail,
            Phone = customer.Phone
        })
    .ToListAsync();

这个方案和DistinctBy的效果类似,但如果需要对分组后的记录做额外处理(比如统计每组的数量),GroupBy会更灵活。

性能优化小提示

  • 确保Orders表的Order_Number字段和Customer_Key字段有索引,Customers表的Customer_Key字段(主键应该已经有索引了)也确保是索引字段,这样去重和关联的速度会大幅提升。
  • 尽量只选择DTO需要的字段,不要查询整个实体,减少数据库返回的数据量,提升查询效率。

备注:内容来源于stack exchange,提问作者Turner

火山引擎 最新活动