求助:LINQ Include中OrderBy对关联子项排序无效问题
EF Core中Include关联集合排序后ProjectTo不生效的解决方法
问题场景
使用EF Core查询采购订单时,尝试通过Include(x => x.PurchaseOrderLineItems.OrderBy(x => x.LineItemId))对关联的行项目排序,但通过AutoMapper的ProjectTo投影到PurchaseOrderDetailDto后,PurchaseOrderLineItems并未按LineItemId升序排列。
原因分析
Include中的OrderBy是指导EF Core加载实体对象时对关联集合排序,但ProjectTo会直接生成SQL将数据投影到DTO,不会加载完整的实体对象,因此Include里的排序规则不会被AutoMapper继承到投影过程中。
解决方案
方案1:在LINQ查询中直接对集合排序后投影
在查询时显式对关联集合排序,再映射到DTO字段:
return await context.PurchaseOrders .Where(x => x.PurchaseOrderNumber == PurchaseOrderNumber) .Select(x => new PurchaseOrderDetailDto { // 映射采购订单的其他字段,例如: PurchaseOrderNumber = x.PurchaseOrderNumber, CreateTime = x.CreateTime, // 对行项目排序后映射 PurchaseOrderLineItems = x.PurchaseOrderLineItems .OrderBy(item => item.LineItemId) .Select(item => new PurchaseOrderLineItemDto { LineItemId = item.LineItemId, ProductName = item.ProductName, Quantity = item.Quantity // 其他行项目字段... }) .ToList() }) .SingleOrDefaultAsync();
方案2:在AutoMapper配置中指定集合排序
在AutoMapper的Profile配置里,为集合成员添加排序逻辑,后续所有投影都会自动应用排序:
public class PurchaseOrderProfile : Profile { public PurchaseOrderProfile() { // 配置采购订单到DTO的映射,指定行项目排序 CreateMap<PurchaseOrder, PurchaseOrderDetailDto>() .ForMember(dest => dest.PurchaseOrderLineItems, opt => opt.MapFrom(src => src.PurchaseOrderLineItems.OrderBy(item => item.LineItemId))); // 配置行项目到DTO的映射 CreateMap<PurchaseOrderLineItem, PurchaseOrderLineItemDto>(); } }
修改后的查询无需在Include中加排序,直接投影即可:
return await context.PurchaseOrders .Where(x => x.PurchaseOrderNumber == PurchaseOrderNumber) .ProjectTo<PurchaseOrderDetailDto>(mapper.ConfigurationProvider) .SingleOrDefaultAsync();
内容的提问来源于stack exchange,提问作者michael
相关产品推荐
相关产品推荐

