EntityFramework LINQ查询计数失败,但查询返回结果。 如何优化LINQ查询?

我有以下LINQ查询执行自我左外连接。 查询看起来有点复杂,但只是简单地进行自我连接(目的是将每条记录与前一个工作日的记录连接起来),然后进行一些参数化过滤。

var newBreakThreshold = decimal.Parse(WebConfigurationManager.AppSettings["NewBreakThreshold"]); using (var dbContext = new NavFoToBoCompareDbContext()) { var query = from current in dbContext.NAVSummaries let currentWD = SqlFunctions.DatePart("dw", current.ValueDate) let currentPD = DbFunctions.AddDays(current.ValueDate, currentWD == 2 ? -3 : currentWD == 1 ? -2 : -1).Value join previous in dbContext.NAVSummaries on new { current.Portfolio, PD = currentPD } equals new { previous.Portfolio, PD = previous.ValueDate } into previousGroup from previous in previousGroup.DefaultIfEmpty() // LEFT OUTER JOIN select new { outer = current, inner = previous }; if (dateStart.HasValue) query = query.Where(e => e.outer.ValueDate >= dateStart.Value); if (dateEnd.HasValue) query = query.Where(e => e.outer.ValueDate  e.outer.Portfolio.Equals(portfolio, StringComparison.OrdinalIgnoreCase)); if (!owner.Equals("ALL", StringComparison.OrdinalIgnoreCase)) query = query.Where(e => e.outer.PortfolioOwner.Equals(owner, StringComparison.OrdinalIgnoreCase)); if (status != 0) query = query.Where(e => e.outer.Statuses.Any(s => s.StatusId == status)); var query2 = query.Select(s => new { BackOfficeNAV = s.outer.BackOfficeNAV, FrontOfficeNAV = s.outer.FrontOfficeNAV, Threshold = s.outer.Threshold, ExtractId = s.outer.ExtractId, ExtractStatus = s.outer.ExtractStatus, PortfolioOwner = s.outer.PortfolioOwner, DateTimeModified = s.outer.DateTimeModified, MostCorrectNAV = s.outer.MostCorrectNAV, Comments = s.outer.Comments, Statuses = s.outer.Statuses, Extracts = s.outer.Extracts, Portfolio = s.outer.Portfolio, ValueDate = s.outer.ValueDate, DifferencePercent = s.outer.DifferencePercent, DayOverDayChange = s.outer.DifferencePercent - s.inner.DifferencePercent, IsChange = s.inner.DifferencePercent != s.outer.DifferencePercent, PreviousValueDate = s.inner.ValueDate, PreviousDifferencePercent = s.inner.DifferencePercent }); query2 = query2.Where(r => "NEW".Equals(breakOption, StringComparison.OrdinalIgnoreCase) ? ((r.DifferencePercent > r.Threshold) && r.IsChange && r.DayOverDayChange > newBreakThreshold) : "OLD".Equals(breakOption, StringComparison.OrdinalIgnoreCase) ? (r.DifferencePercent > r.Threshold) : "ALL".Equals(breakOption, StringComparison.OrdinalIgnoreCase)); var resultCount = query2.Count(); } 

该查询在两个地方使用。 在一种方法中,它用于计算分页所需的计数。 在另一种方法中,它用于从数据库中获取实际结果。 获取更大结果集的实际结果的实现成功执行,而Count()查询失败并带有Timeoutexception。 注意:两种实现方式完全相同。

也有人可以帮我优化这个查询。 提前致谢。

不太确定这是问题,但至少让我们尝试通过手动构建具有常量值的表达式来消除dateStart / dateEnd参数来消除所谓的参数嗅探问题的潜在影响。

首先,一个小帮手方法:

 using System; using System.Linq; using System.Linq.Expressions; public static class QueryableUtils { public static IQueryable WhereBetween(this IQueryable source, Expression> dateSelector, DateTime? startDate, DateTime? endDate) { if (startDate == null && endDate == null) return source; var startCond = startDate != null ? Expression.GreaterThanOrEqual(dateSelector.Body, Expression.Constant(startDate.Value)) : null; var endCond = endDate != null ? Expression.LessThanOrEqual(dateSelector.Body, Expression.Constant(endDate.Value)) : null; var predicate = Expression.Lambda>( startCond == null ? endCond : endCond == null ? startCond : Expression.AndAlso(startCond, endCond), dateSelector.Parameters[0]); return source.Where(predicate); } } 

然后尝试以下操作,看看它是否有帮助:

 //if (dateStart.HasValue) // query = query.Where(e => e.outer.ValueDate >= dateStart.Value); //if (dateEnd.HasValue) // query = query.Where(e => e.outer.ValueDate <= dateEnd.Value); query = query.WhereBetween(e => e.outer.ValueDate, dateStart, dateEnd); 

您可以简单地使用AsParallel()来启用linq查询的multithreading执行。 然后,您应该检查表的索引以提高性能。