public async Task UpdateAsync(string feature) { if (_processedFeatures.Contains(feature)) { return; } _processedFeatures.Add(feature); if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Updating feature: {0}", feature); } // proceed with dependent features first, whatever the module it's in var dependencies = _extensionManager.AvailableFeatures() .Where(f => String.Equals(f.Id, feature, StringComparison.OrdinalIgnoreCase)) .Where(f => f.Dependencies != null) .SelectMany(f => f.Dependencies) .ToList(); foreach (var dependency in dependencies) { await UpdateAsync(dependency); } var migrations = GetDataMigrations(feature); // apply update methods to each migration class for the module foreach (var migration in migrations) { _session.ExecuteMigration(schemaBuilder => { migration.SchemaBuilder = schemaBuilder; // copy the object for the Linq query var tempMigration = migration; // get current version for this migration var dataMigrationRecord = GetDataMigrationRecordAsync(tempMigration).Result; var current = 0; if (dataMigrationRecord != null) { current = dataMigrationRecord.Version.Value; } else { dataMigrationRecord = new Records.DataMigration { DataMigrationClass = migration.GetType().FullName }; _dataMigrationRecord.DataMigrations.Add(dataMigrationRecord); } try { // do we need to call Create() ? if (current == 0) { // try to resolve a Create method var createMethod = GetCreateMethod(migration); if (createMethod != null) { current = (int)createMethod.Invoke(migration, new object[0]); } } var lookupTable = CreateUpgradeLookupTable(migration); while (lookupTable.ContainsKey(current)) { try { if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Applying migration for {0} from version {1}.", feature, current); } current = (int)lookupTable[current].Invoke(migration, new object[0]); } catch (Exception ex) { if (ex.IsFatal()) { throw; } _logger.LogError(0, "An unexpected error occurred while applying migration on {0} from version {1}.", feature, current); throw; } } // if current is 0, it means no upgrade/create method was found or succeeded if (current == 0) { return; } dataMigrationRecord.Version = current; } catch (Exception ex) { if (ex.IsFatal()) { throw; } _logger.LogError(0, "Error while running migration version {0} for {1}.", current, feature); _session.Cancel(); throw new OrchardException(T("Error while running migration version {0} for {1}.", current, feature), ex); } finally { // Persist data migrations _session.Save(_dataMigrationRecord); } }); } }
public async Task UpdateAsync(string feature) { if (_processedFeatures.Contains(feature)) { return; } _processedFeatures.Add(feature); if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Updating feature: {0}", feature); } // proceed with dependent features first, whatever the module it's in var dependencies = _extensionManager.AvailableFeatures() .Where(f => String.Equals(f.Id, feature, StringComparison.OrdinalIgnoreCase)) .Where(f => f.Dependencies != null) .SelectMany(f => f.Dependencies) .ToList(); foreach (var dependency in dependencies) { await UpdateAsync(dependency); } var migrations = GetDataMigrations(feature); // apply update methods to each migration class for the module foreach (var migration in migrations) { _session.ExecuteMigration(schemaBuilder => { migration.SchemaBuilder = schemaBuilder; // copy the object for the Linq query var tempMigration = migration; // get current version for this migration var dataMigrationRecord = GetDataMigrationRecordAsync(tempMigration).Result; var current = 0; if (dataMigrationRecord != null) { current = dataMigrationRecord.Version.Value; } else { dataMigrationRecord = new DataMigration { DataMigrationClass = migration.GetType().FullName }; _dataMigrationRecord.DataMigrations.Add(dataMigrationRecord); } try { // do we need to call Create() ? if (current == 0) { // try to resolve a Create method var createMethod = GetCreateMethod(migration); if (createMethod != null) { current = (int)createMethod.Invoke(migration, new object[0]); } } var lookupTable = CreateUpgradeLookupTable(migration); while (lookupTable.ContainsKey(current)) { try { if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Applying migration for {0} from version {1}.", feature, current); } current = (int)lookupTable[current].Invoke(migration, new object[0]); } catch (Exception ex) { if (ex.IsFatal()) { throw; } _logger.LogError(0, "An unexpected error occurred while applying migration on {0} from version {1}.", feature, current); throw; } } // if current is 0, it means no upgrade/create method was found or succeeded if (current == 0) { return; } dataMigrationRecord.Version = current; } catch (Exception ex) { if (ex.IsFatal()) { throw; } _logger.LogError(0, "Error while running migration version {0} for {1}.", current, feature); _session.Cancel(); throw new OrchardException(T("Error while running migration version {0} for {1}.", current, feature), ex); } finally { // Persist data migrations _session.Save(_dataMigrationRecord); } }); } }