internal async Task UpdateTrainingCatalogAsync(UpdateDbContext context, TrainingProvider trainingProvider, string description, ServerMediaPathsContainer pathsContainer, bool useArchiveData = false, bool logUpdateToDb = true) { var updateEvent = new UpdateEvent(trainingProvider.Id, description, _dateTimeProxy.UtcNow); context.UpdateEvents.Add(updateEvent); await context.SaveChangesAsync(); using (var catalog = _activatorProxy.CreateInstance<ITrainingCatalog>(trainingProvider.AssemblyType)) { catalog.Initialize(trainingProvider.Name, trainingProvider.Id, trainingProvider.SiteUrl, trainingProvider.SourceUrl, trainingProvider.SourceLocation, pathsContainer,_archiveDirectoryPath); try { await catalog.UpdateAsync(updateEvent, context, useArchiveData, logUpdateToDb); updateEvent.EndedOn = _dateTimeProxy.UtcNow; if (context.AuthorsResolves.Local.Any()) { updateEvent.UpdateResult = UpdateResult.NeedManualResolve; } else { updateEvent.UpdateResult = UpdateResult.Success; } await context.SaveChangesAsync(); } catch (Exception ex) { updateEvent.EndedOn = _dateTimeProxy.UtcNow; updateEvent.UpdateResult = UpdateResult.Error; var aggregateException = ex as AggregateException; var errorData = aggregateException != null ? aggregateException.Flatten().ToString() : ex.ToString(); updateEvent.ErrorData = errorData; updateEvent.AuthorsUpdates = null; updateEvent.CategoriesUpdates = null; updateEvent.CoursesUpdates = null; context.SetStateToDetached(updateEvent); using (var ctx = _contextFactory.CreateDbContext()) { ctx.SetStateToModified(updateEvent); ctx.SaveChanges(); } } } }
/// <exception cref="ArgumentNullException"> /// <paramref name="updateEvent"/> or /// <paramref name="changesProcessor"/> is <see langword="null" />.</exception> /// <exception cref="ChangesProcessorException"></exception> /// <exception cref="UpdateProcessorException"></exception> public async Task ProcessUpdateAsync(UpdateEvent updateEvent, TrainingCatalogChangesProcessor <TCategoryParseModel, TCourseParseModel, TAuthorParseModel> changesProcessor) { if (updateEvent == null) { throw new ArgumentNullException("updateEvent"); } if (changesProcessor == null) { throw new ArgumentNullException("changesProcessor"); } UpdateEvent = updateEvent; // order of the calls is important: (categories or authors) -> courses !!! var existingCategories = await Context.Categories .Where(x => x.TrainingProviderId == TrainingProviderId) .AsNoTracking() .ToListAsync(); var categoriesChanges = await changesProcessor.GetCategoriesChangesAsync(TrainingProviderId, existingCategories, CatalogBackupProcessor.CategoryBackupCreator); var existingAuthors = await Context.TrainingProviderAuthors .Where(x => x.TrainingProviderId == TrainingProviderId) .AsNoTracking() .ToListAsync(); var authorsChanges = await changesProcessor.GetAuthorsChangesAsync(TrainingProviderId, existingAuthors, CatalogBackupProcessor.AuthorBackupCreator); var existingCourses = await Context.Courses .Include(x => x.CourseAuthors) .Where(x => x.TrainingProviderId == TrainingProviderId) .ToListAsync(); var coursesChanges = await changesProcessor.GetCoursesChangesAsync(TrainingProviderId, existingCourses, CatalogBackupProcessor.CourseBackupCreator); var authorResolves = await Context.AuthorsResolves .Where(x => x.ResolveState == ResolveState.Resolved && x.TrainingProviderId == TrainingProviderId) .AsNoTracking().ToListAsync(); try { TrainingManagerDbConfiguration.SuspendExecutionStrategy = true; using (var transaction = Context.Database.BeginTransaction()) { await UpdateCategoriesAsync(categoriesChanges); await UpdateAuthorsAsync(authorsChanges, authorResolves); await UpdateCoursesAsync(coursesChanges, authorResolves); transaction.Commit(); } } finally { TrainingManagerDbConfiguration.SuspendExecutionStrategy = false; } }