public static async Task <ScheduleViewItemsGroup> LoadAsync(Guid localAccountId, Guid semesterId, bool trackChanges = true, bool includeWeightCategories = true) { ScheduleViewItemsGroup answer; bool usedCached = false; // Find a cached match // Note that if the requester doesn't require weight categories, we'll ignore checking that includeWeightCategories matches, // since returning a cache that includes weight categories doesn't harm anything. lock (_cachedItems) { var cached = _cachedItems.FirstOrDefault(i => i.LocalAccountId == localAccountId && i.SemesterId == semesterId && (!includeWeightCategories || i._includeWeightCategories == includeWeightCategories)); // If we'd like the changes tracked and we already have a matching cached if (trackChanges && cached != null) { usedCached = true; answer = cached; } else { // Otherwise, no cached or no change tracking requested, so load new answer = new ScheduleViewItemsGroup(localAccountId, semesterId, trackChanges, includeWeightCategories); answer._loadingTask = Task.Run(answer.LoadBlocking); // If we're tracking changes, we'll add it to the cached if (trackChanges) { _cachedItems.Add(answer); } } } try { await answer._loadingTask; return(answer); } catch { if (usedCached) { // If we were using cached and it previously failed to load, // we remove it and try again lock (_cachedItems) { _cachedItems.Remove(answer); } } else { throw; } } // We try to load again since we used cached and it failed previously return(await LoadAsync(localAccountId, semesterId, trackChanges : trackChanges, includeWeightCategories : includeWeightCategories)); }
protected async Task LoadBlocking(Guid examId) { var dataStore = await GetDataStore(); if (dataStore == null) { throw new NullReferenceException("Account doesn't exist"); } DataItemMegaItem dataItem; // We need ALL classes loaded, including their schedules, and their weight categories. // Might as well just use ScheduleViewItemsGroup therefore. Guid semesterId; Guid classId = Guid.Empty; using (await Locks.LockDataForReadAsync("BaseSingleItemViewItemsGroup.LoadBlocking")) { dataItem = dataStore.TableMegaItems.FirstOrDefault(i => i.Identifier == examId); if (dataItem == null) { TelemetryExtension.Current?.TrackEvent("Error_LoadSingleItem_CouldNotFind", new Dictionary <string, string>() { { "ItemId", examId.ToString() } }); // Leave the Item set to null return; } if (dataItem.MegaItemType == PowerPlannerSending.MegaItemType.Task || dataItem.MegaItemType == PowerPlannerSending.MegaItemType.Event) { semesterId = dataItem.UpperIdentifier; classId = dataItem.UpperIdentifier; } else { var dataClass = dataStore.TableClasses.FirstOrDefault(i => i.Identifier == dataItem.UpperIdentifier); if (dataClass == null) { throw new NullReferenceException("Class not found. Item id " + examId); } semesterId = dataClass.UpperIdentifier; classId = dataClass.Identifier; } } _scheduleViewItemsGroup = await ScheduleViewItemsGroup.LoadAsync(LocalAccountId, semesterId : semesterId, trackChanges : trackChanges, includeWeightCategories : true); // Grab the class for the item ViewItemClass viewClass; if (dataItem.MegaItemType == PowerPlannerSending.MegaItemType.Task || dataItem.MegaItemType == PowerPlannerSending.MegaItemType.Event) { viewClass = _scheduleViewItemsGroup.Semester.NoClassClass; } else { viewClass = _scheduleViewItemsGroup.Semester.Classes.FirstOrDefault(i => i.Identifier == classId); if (viewClass == null) { throw new NullReferenceException("ViewItemClass not found. Item id " + examId); } } // And create the item Item = CreateItem(dataItem, viewClass); }