LINQ左连接中仅获取Orders表第一条记录的实现问题
LINQ实现左连接并仅取每个客户的第一条订单
原代码的问题在于直接在join子句中调用orders.FirstOrDefault(x => x.CustomerId == customer.CustomerId)是错误的:
FirstOrDefault返回单个Order对象,不是可枚举集合,不符合join操作对数据源的要求- 子查询中的
customer变量无法被LINQ正确识别(上下文作用域问题)
完全可以用LINQ实现需求,以下是两种可行写法:
写法一:查询语法
先对订单按客户ID分组,每组取第一条订单,再与客户表做左连接,最后关联配送信息:
var customerOrder = (from customer in customers // 先获取每个客户的第一条订单 join order in orders.GroupBy(o => o.CustomerId) .Select(g => g.FirstOrDefault()) on customer.CustomerId equals order.CustomerId into orderGroup // 左连接处理,没有订单的客户保留null from order in orderGroup.DefaultIfEmpty() // 左连接配送信息 join shipping in shipping on customer.CustomerId equals shipping.CustomerId into shippingGroup from shipping in shippingGroup.DefaultIfEmpty() select new { customer.CustomerId, Order = order, Shipping = shipping }).ToList();
写法二:方法语法
在客户的Select操作中直接获取对应第一条订单,再关联配送信息:
var customerOrder = customers.Select(c => new { c.CustomerId, Order = orders.FirstOrDefault(o => o.CustomerId == c.CustomerId), Shipping = shipping.FirstOrDefault(s => s.CustomerId == c.CustomerId) }).ToList();
如果需要保留客户的所有配送记录(一个客户多条配送信息),可以调整为:
var customerOrder = customers.SelectMany(c => shipping.Where(s => s.CustomerId == c.CustomerId) .DefaultIfEmpty(), (c, s) => new { c.CustomerId, Order = orders.FirstOrDefault(o => o.CustomerId == c.CustomerId), Shipping = s }).ToList();
补充说明
如果订单有明确的排序规则(比如按创建时间取最新/最早),建议在FirstOrDefault前加上OrderBy/OrderByDescending,比如orders.Where(o => o.CustomerId == c.CustomerId).OrderByDescending(o => o.CreateTime).FirstOrDefault(),确保取到的是预期的第一条订单
内容的提问来源于stack exchange,提问作者AtomicallyBeyond
相关产品推荐
相关产品推荐

