如何简化抛出超时异常的LINQ查询?
简化超时的LINQ查询并优化性能
嘿,我看你这个LINQ查询抛出了超时异常,帮你简化优化一下,不仅代码更清爽,还能解决性能问题:
原查询抛出的异常:
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
原查询代码:
return await base.Execute((dataContext) => { var demo = (from proj in dataContext.ProjectStats select new { a = proj } into sam group sam by new { sam.a.ClassTypeID, sam.a.StudentID } into gcs select gcs.Select(x => new Dao.ProjectStat() { StudentID = gcs.Key.StudentID, ClassTypeID = gcs.Key.ClassTypeID, CompletedCount = gcs.Sum(y => y.a.CompletedCount), FinishedTime = x.a.FinishedTime })).SelectMany(g => g).SelectObject(); return demo.ToList(); });
简化优化后的版本
return await base.Execute(async dataContext => { var result = await dataContext.ProjectStats // 直接按目标字段分组,砍掉多余的中间匿名类 .GroupBy(ps => new { ps.ClassTypeID, ps.StudentID }) .Select(g => new Dao.ProjectStat { StudentID = g.Key.StudentID, ClassTypeID = g.Key.ClassTypeID, // 分组内只计算一次总和,避免原查询重复计算的性能浪费 CompletedCount = g.Sum(ps => ps.CompletedCount), // 注意:原逻辑会为分组内每条记录生成对象,FinishedTime取单条值 // 如果业务需要分组统一时间(比如最新/最早),建议改成Max/Min,比如: // FinishedTime = g.Max(ps => ps.FinishedTime) FinishedTime = g.First().FinishedTime // 若要保留原多对象逻辑,用First或按需取值 }) .SelectObject() // 用异步ToListAsync替代同步ToList,贴合异步场景 .ToListAsync(); return result; });
优化说明
- 砍掉了原查询里多余的中间匿名类
sam,减少了不必要的对象创建和查询层级,让数据库生成的SQL更高效 - 原查询在分组后的
Select里反复调用gcs.Sum,会导致数据库对同一个分组多次计算总和,现在只计算一次,直接降低数据库压力 - 替换同步的
ToList()为异步的ToListAsync(),更符合异步编程的最佳实践,避免线程阻塞 - 额外提醒:原逻辑会为分组内的每一条记录都生成一个
ProjectStat对象,除了FinishedTime不同,其他字段都是分组的统一值,这大概率不是业务需要的。如果是要做分组聚合,建议用Max/Min取分组内的时间,或者明确业务需求后调整,不然会生成大量重复数据,进一步拖慢查询
内容的提问来源于stack exchange,提问作者sbm6070
相关产品推荐
相关产品推荐

