如何在初始化列表前获取查询中的Val4值?MVC&EF问题
直接在LINQ查询中计算Val4,避免重复ToList()
嘿,刚接触MVC和Entity Framework的时候,很容易不小心写出需要多次加载数据到内存的代码,你察觉到两次初始化列表是浪费时间这点非常棒!完全可以在初始的LINQ查询里直接计算出Val4,不用先把数据拉到内存再循环赋值,还能省去一次ToList()的开销。
先分析你当前代码的问题
你现在的流程是:
- 执行查询并加载数据到内存(第一次
ToList()) - 遍历列表给
Val4赋值 - 再次排序并重新生成列表(第二次
ToList())
这不仅多了一次内存操作,Val4的计算还在客户端内存完成,其实我们可以把这些逻辑都推送到数据库层面,让SQL帮我们完成计算和排序,性能会更好。
优化后的代码
var query = from p in db.Table1 join s in db.Table2 on p.ID equals s.sID join m in db.Table3 on s.sID equals m.ID group s by p into G let val2 = G.Sum(x => x.someVal) let val3 = (from Z in db.Table4 join p in db.Table5 on Z.ID equals p.ZamowienieID select (decimal)p.otherVal).DefaultIfEmpty(0).Sum() select new Row { Val1 = G.Key, Val2 = val2, Val3 = val3, Val4 = val3 / (val2 + val3) * 100 } .OrderBy(x => x.Val4); var list = query.ToList();
关键优化点说明
- 用
let关键字缓存计算值:val2和val3分别缓存了分组求和的结果,避免重复计算,同时让代码更清晰。 - 直接在查询中计算Val4:把
Val4的计算逻辑放到select里,Entity Framework会把这个计算转化为SQL语句,在数据库层面完成,不用拉到内存再处理。 - 类型转换提前处理:把
p.otherVal转为decimal,避免整数除法导致的精度丢失问题(比如如果都是整数的话,1/2会得到0而不是0.5)。 - 排序整合到查询中:把
OrderBy放到初始查询里,这样排序也会在数据库层面完成,不用先加载所有数据到内存再排序。 - 只调用一次
ToList():整个查询逻辑完成后,只需要一次ToList()就把最终结果加载到内存,避免了重复的内存操作。
这样修改后,不仅代码更简洁,性能也会更好,因为大部分计算都在数据库端完成,减少了客户端和数据库之间的数据传输量。
内容的提问来源于stack exchange,提问作者Damian Szechlicki
相关产品推荐
相关产品推荐

