I have the following code that unfortunately is really slow:
private void FilterSessionByDate()
{
SessionsFilteredByDate =
BusinessClient.Instance.Tracker.GetAllMilestonesInSessionObjects().Where(
i => i.CreatedDate >= GetFromDate() && i.CreatedDate <= GetToDate());
}
private void FilterSessionsByTrackerId()
{
SessionsFilteredByDateAndTrackerId =
SessionsFilteredByDate.Where(i=>i.TrackerId == CurrentItem.ID);
}
private void BindGrid(DateTime fromDate, DateTime toDate, int trackerId, int campaignId)
{
var result = BusinessClient.Instance.Tracker.GetReportForCampaign(trackerId, campaignId, fromDate, toDate);
foreach (var trackerReport in result)
{
trackerReport.Errors = GetErrors(trackerReport);
}
StatisticsGrid.DataSource = result.Where(r => r.ParentMilestoneId == null);
StatisticsGrid.DataBind();
}
private int GetErrors(TrackerReport milestone)
{
int counter = 0;
//var milestonesWithId = BusinessClient.Instance.Tracker.GetAllMilestonesInSessionWithTrackerId(CurrentItem.ID);
//var sessionsWithDateRange = milestonesWithId.Where(i=> i.CreatedDate >= GetFromDate() && i.CreatedDate <= GetToDate());
var sessionsWithStatusError = SessionsFilteredByDateAndTrackerId.Where(i => i.StatusId == 0);
foreach (var milestonesInSession in sessionsWithStatusError)
{
// Get all milestoneinsessions with this session
MilestonesInSession session = milestonesInSession;
var localPath = BusinessClient.Instance.Tracker.GetAllMilestonesInSessionObjects().Where(
i => i.SessionId == session.SessionId).ToList();
var lastStep = localPath.Max(i => i.MilestoneId);
var latestTime = localPath.Where(i => i.MilestoneId != lastStep).Max(i=>i.CreatedDate);
var milestoneWithLatestTime = localPath.First(x => x.CreatedDate == latestTime);
if (milestonesInSession.MilestoneId != milestone.MilestoneId)
{
if (milestoneWithLatestTime.MilestoneId == milestone.MilestoneId &&
milestoneWithLatestTime.CreatedDate.AddSeconds(2) >= milestonesInSession.CreatedDate)
counter++;
}
else
{
// It is the last milestone, we have to check if the milestone with
// the latest time is close to this one, otherwise the error happened
// at the last step
if (milestonesInSession.CreatedDate > milestoneWithLatestTime.CreatedDate.AddSeconds(2))
counter++;
}
}
return counter;
}
The MilestonesInSessions
in the database are 2 millions, but I managed to optimize the queries, so that the retrieving of them are pretty fast. Anyway, having multiple nested foreach
affects its speed, given that:
- The
result
variable is always with 10 entries. - The
sessionStatusWithError
variable has generally around 100 entries. - The
localpath
variable is always with 10 entries.
IQueryable
[RequiresDataAccessSynchronized]
public IQueryable<MilestonesInSession> GetAllMilestonesInSessionObjects()
{
var query = from m in _milestonesInSessionRepository.GetAll()
select m;
return query;
}
MilestonesInSession
public class MilestonesInSession : DataAccessBase2, IDataOperations<Model.Tracker.MilestonesInSession, Model.Tracker.MilestonesInSession>
{
#region IDataOperations<MilestonesInSession,int> Members
public IQueryable<Model.Tracker.MilestonesInSession> GetAll()
{
var query = from milestoneSession in _dataContext.Repository<Linq.TrackerMilestonesInSession>()
select new Model.Tracker.MilestonesInSession
{
MilestoneId = milestoneSession.MilestoneId,
CreatedDate = milestoneSession.CreatedDate,
SessionId = milestoneSession.SessionId,
ProductId = milestoneSession.ProductId,
TrackerId = milestoneSession.TrackerId,
StatusId = milestoneSession.StatusId,
BankId = milestoneSession.BankId
};
return query;
}
Ants Performance profiler screenshots:
Do you know how can I optimize it to get a instant/better result instead of waiting at least 10 seconds every time?
.GetAllMilestonesInSessionObjects()
lazy-loading, or does it get all Milestones from the DB and then the.Where()
filters them? \$\endgroup\$