能否通过投影优化关联表计算列查询以降低数据开销?
优化Radzen Blazor中OrderShipping的Weight计算性能
问题分析
当前通过Include加载完整关联数据后在内存循环计算Weight,会导致EF返回大量冗余数据(如OrderShippingDetails、Product1的所有字段),性能开销大。由于自动生成的EnergyOracleService.cs无法修改,需在Custom文件中通过EF投影实现数据库层面的计算,减少数据传输量。
解决方案
修改EnergyOracleService.Custom.cs中的OnOrderShippingsRead方法,使用Select投影直接在数据库端计算Weight,仅查询所需字段:
public partial class EnergyOracleService { partial void OnOrderShippingsRead(ref IQueryable<OrderShipping> items) { // 替换原Include+循环逻辑,改用投影实现数据库端计算 items = items.Select(os => new OrderShipping { // 必须列出OrderShipping实体的所有数据库映射字段(根据实际实体结构补充) Id = os.Id, OrderId = os.OrderId, ShippingMethod = os.ShippingMethod, TrackingNumber = os.TrackingNumber, CreatedDate = os.CreatedDate, // ... 其他所有数据库同步的实体字段 // 在数据库层面计算Weight总和,避免加载冗余关联数据 Weight = os.OrderShippingDetails .Where(osd => osd.OrderDetail1.Order == osd.OrderShipping1.Order) .Sum(osd => (osd.OrderDetail1.Product1.Weight2 ?? 0) * osd.Quantity) }); } }
关键说明
- 投影优势:EF会生成仅包含指定字段的SQL查询,不会加载
OrderShippingDetails、Product1的冗余字段,大幅降低数据库返回的数据量。 - 数据库端计算:
Sum操作直接在数据库执行,比内存循环求和性能提升显著。 - 字段完整性:必须手动列出
OrderShipping的所有数据库映射字段,否则未指定的字段会取默认值(如0、null),导致UI显示异常。 - 过滤逻辑保留:原
Where条件(关联数据的过滤)直接嵌入投影的Sum查询中,确保计算逻辑与原逻辑一致。
注意事项
- 若
OrderShipping实体字段较多,可考虑引入AutoMapper简化投影映射(需自行安装配置),避免手动罗列字段的繁琐。 - 原代码中的
Include、AsSplitQuery可完全移除,投影已明确指定所需的关联计算逻辑,无需加载完整关联集合。
内容的提问来源于stack exchange,提问作者Ian
相关产品推荐
相关产品推荐

