I have the following LINQ query that does self-left-external-join. The queries look a bit complicated, but just make an independent connection to yourself (the goal is to join each record with the record for the previous working day), and then perform some parameterized filtering.
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 <= dateEnd.Value); if (!portfolio.Equals("ALL", StringComparison.OrdinalIgnoreCase)) query = query.Where(e => 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(); }
The request is used in two places. In one method, it was used to calculate the amount needed for pagination. In another method, it is used to obtain actual results from a database. The implementation to obtain actual results for a larger set of results is successful, while the Count () query completes using the Timeout exception. Note. Both implementations are the same.
Can someone help me in optimizing this query. Thanks in advance.