这次性能问题还是多表连接查询却没走筛选条件的问题。
测试人员反应一查询接口耗时数秒,偶尔还500,让我看看。审查代码发现查询Where筛选条件是有的,不过传递的是一个Func委托,在Func委托内进一步进行筛选。分析sql发现EF根本没走筛选条件。简略Lambda如下:
Func<IFilterEntity, bool> funcFilter = p => FilterData(p); var checkReports = _dbContext.TEntity.Where(p => funcFilter) .Select(x => Mapper.Map<OutPut>(x) .Concat(相同的方式关联6个同样使用带Func<IFilterEntity, bool>筛选条件的表)
其中Where筛选传入了一个FilterData方法,将p当作一个动态对象将传入的参数对比对象属性来进行判断。然后发现EF根本不解析FilterData,直接返回整张表,然后在内存中进行FilterData。
查看Where的入参发现Where要的是一个Expression<Func<TSource, bool>>表达式对象而不是Func<TSource, bool>委托对象。
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
经过尝试发现传入的Expression表达式EF是可以进行正确的解析的。于是修改代码如下
Expression<Func<IFilterEntity, bool>> predicate = p => filterFunc; var checkReports = _dbContext.TEntity.Where(predicate).Select(x => Mapper.Map<OutPut>(x));
修改后查询稳定在200ms以内。
在我想加上非跟踪进一步优化性能后我发现查询的速度与默认跟踪基本没有差别,想来可能是微软优化的已经非常完善了。