/// <summary> /// Build the migration plan. /// </summary> /// <param name="loggerFactory">The factory for creating <see cref="ILogger"/> instances.</param> /// <exception cref="InvalidOperationException">Thrown when a required resource was not specified.</exception> /// <returns>A <see cref="Migration">Migration Plan</see>.</returns> public IMigration Build(ILoggerFactory loggerFactory) { if (this.connectionFactory == null) { throw FlightExceptionFactory.InvalidOperation("CannotBuildWithoutConnectionFactory"); } if (this.batchManager == null) { throw FlightExceptionFactory.InvalidOperation("CannotBuildWithoutBatchManager"); } if (this.auditor == null) { throw FlightExceptionFactory.InvalidOperation("CannotBuildWithoutAuditor"); } if (this.scriptExecutor == null) { throw FlightExceptionFactory.InvalidOperation("CannotBuildWithoutScriptExecutor"); } Log.SetLogger(loggerFactory.CreateLogger(typeof(Migration))); return(new Migration( this.connectionFactory, this.scriptExecutor, this.auditor, this.batchManager, this.initializationScriptProvider, this.migrationScriptProvider)); }
/// <summary> /// <inheritdoc cref="IMigration.MigrateAsync(CancellationToken)"/> /// </summary> /// <param name="cancellationToken">The token used to notify that operations should be canceled.</param> /// <returns>A task that represents the asynchronous operation.</returns> public async Task MigrateAsync(CancellationToken cancellationToken = default) { Log.Info("Migration started"); try { using var connection = this.connectionFactory.Create(); await connection.OpenAsync(cancellationToken).ConfigureAwait(false); var initializationScripts = this.initializationScriptProvider.GetScripts(); Log.Info($"{initializationScripts.Count()} initialization script(s) loaded."); foreach (var script in initializationScripts) { Log.Info($"Executing initialization script {script.ScriptName}, Checksum: {script.Checksum}"); Log.Debug(script.Text); foreach (var commandText in this.batchManager.Split(script)) { using var command = connection.CreateCommand(); command.CommandText = commandText; command.CommandType = System.Data.CommandType.Text; await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false); } } await this.auditLog.EnsureCreatedAsync(connection, cancellationToken).ConfigureAwait(false); await this.auditLog.StoreEntriesAsync(connection, null, initializationScripts, cancellationToken).ConfigureAwait(false); var auditLogEntries = await this.auditLog.LoadEntriesAsync(connection, cancellationToken).ConfigureAwait(false); var changeSet = this.CreateChangeSet(auditLogEntries); if (changeSet.Count > 0) { await this.scriptExecutor.ExecuteAsync(connection, changeSet, this.batchManager, this.auditLog, cancellationToken).ConfigureAwait(false); } } catch (FlightException) { throw; } catch (Exception ex) { var unknown = FlightExceptionFactory.Unknown(ex); Log.Error(unknown, unknown.Message); throw unknown; } Log.Info("Migration completed"); }