/// <summary> /// Creates a new database using DbSchema. /// </summary> /// <param name="databaseName">a name of the new database to create</param> /// <param name="dbSchemaFolderPath">the path to the folder that contains gauge schema files /// (all files loaded in order to support plugins that may require their own tables)</param> /// <param name="forExtensions">a list of extensions Guid's to include in schema; /// if null or empty all schema files will be included</param> /// <remarks>After creating a new database the <see cref="CurrentDatabase">CurrentDatabase</see> /// property should be set to the new database name.</remarks> /// <exception cref="ArgumentNullException">databaseName is not specified</exception> /// <exception cref="ArgumentNullException">dbSchemaFolderPath is not specified</exception> /// <exception cref="ArgumentException">dbSchemaFolderPath contains one or more invalid characters /// as defined by InvalidPathChars.</exception> /// <exception cref="PathTooLongException">The specified dbSchemaFolderPath, file name, or both exceed /// the system-defined maximum length. For example, on Windows-based platforms, /// paths must be less than 248 characters, and file names must be less than 260 characters.</exception> /// <exception cref="DirectoryNotFoundException">The specified dbSchemaFolderPath is invalid /// (for example, it is on an unmapped drive).</exception> /// <exception cref="IOException">An I/O error occurred while opening the file.</exception> /// <exception cref="UnauthorizedAccessException">The caller does not have the required permission.</exception> /// <exception cref="FileNotFoundException">The file specified in dbSchemaFolderPath was not found.</exception> /// <exception cref="NotSupportedException">dbSchemaFolderPath is in an invalid format.</exception> /// <exception cref="SecurityException">The caller does not have the required permission.</exception> public Task CreateDatabaseAsync(string dbSchemaFolderPath, Guid[] forExtensions = null) { if (_agent.IsTransactionInProgress) { throw new InvalidOperationException(Properties.Resources.SqlAgentBase_CannotCreateDatabase); } if (dbSchemaFolderPath.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(dbSchemaFolderPath)); } if (!System.IO.Directory.Exists(dbSchemaFolderPath)) { throw new ArgumentException(string.Format( Properties.Resources.DbSchemaFolderDoesNotExistException, dbSchemaFolderPath), nameof(dbSchemaFolderPath)); } var dbSchema = new DbSchema(); dbSchema.LoadXmlFolder(dbSchemaFolderPath, forExtensions); if (dbSchema.Tables.Count < 1) { throw new ArgumentException(Properties.Resources.SqlAgentBase_GaugeSchemaEmpty); } return(CreateDatabaseAsync(dbSchema)); }
/// <summary> /// Compares the current database definition to the gauge definition definition read from /// the file specified and returns a list of DbSchema errors, i.e. inconsistencies found /// and SQL statements to repair them. /// </summary> /// <param name="dbSchemaFolderPath">the path to the folder that contains gauge schema files /// (all files loaded in order to support plugins that may require their own tables)</param> /// <param name="forExtensions">a list of extensions Guid's to include in schema; /// if null or empty all schema files will be included</param> /// <param name="cancellationToken">a cancelation token (if any)</param> /// <exception cref="ArgumentNullException">databaseName is not specified</exception> /// <exception cref="ArgumentNullException">dbSchemaFolderPath is not specified</exception> /// <exception cref="ArgumentException">dbSchemaFolderPath contains one or more invalid characters /// as defined by InvalidPathChars.</exception> /// <exception cref="PathTooLongException">The specified dbSchemaFolderPath, file name, or both exceed /// the system-defined maximum length. For example, on Windows-based platforms, /// paths must be less than 248 characters, and file names must be less than 260 characters.</exception> /// <exception cref="DirectoryNotFoundException">The specified dbSchemaFolderPath is invalid /// (for example, it is on an unmapped drive).</exception> /// <exception cref="IOException">An I/O error occurred while opening the file.</exception> /// <exception cref="UnauthorizedAccessException">The caller does not have the required permission.</exception> /// <exception cref="FileNotFoundException">The file specified in dbSchemaFolderPath was not found.</exception> /// <exception cref="NotSupportedException">dbSchemaFolderPath is in an invalid format.</exception> /// <exception cref="SecurityException">The caller does not have the required permission.</exception> public async Task <List <DbSchemaError> > GetDbSchemaErrorsAsync(string dbSchemaFolderPath, Guid[] forExtensions, CancellationToken cancellationToken) { if (dbSchemaFolderPath.IsNullOrWhiteSpace()) { throw new ArgumentNullException(nameof(dbSchemaFolderPath)); } if (!System.IO.Directory.Exists(dbSchemaFolderPath)) { throw new ArgumentException(string.Format( Properties.Resources.DbSchemaFolderDoesNotExistException, dbSchemaFolderPath), nameof(dbSchemaFolderPath)); } var gaugeSchema = new DbSchema(); gaugeSchema.LoadXmlFolder(dbSchemaFolderPath, forExtensions); if (gaugeSchema.Tables.Count < 1) { throw new ArgumentException(Properties.Resources.SqlAgentBase_GaugeSchemaEmpty); } var actualSchema = await GetDbSchemaAsync(cancellationToken).ConfigureAwait(false); return(this.GetDbSchemaErrors(gaugeSchema, actualSchema)); }
/// <summary> /// Creates a clone of the database using another SqlAgent. /// </summary> /// <param name="cloneManager">an SQL schema manager to use when creating clone database</param> /// <param name="schemaToUse">a database schema to use (enforce), /// if null the schema ir read from the database cloned</param> /// <param name="ct">a cancelation token (if any)</param> /// <param name="progress">a progress callback (if any)</param> public async Task CloneDatabase(SchemaManagerBase cloneManager, DbSchema schemaToUse, IProgress <DbCloneProgressArgs> progress, CancellationToken ct) { if (cloneManager.IsNull()) { throw new ArgumentNullException(nameof(cloneManager)); } progress?.Report(new DbCloneProgressArgs(DbCloneProgressArgs.Stage.FetchingSchema, string.Empty, 0)); if (schemaToUse.IsNull()) { schemaToUse = await GetDbSchemaAsync(ct).ConfigureAwait(false); } if (CloneCanceled(progress, ct)) { return; } progress?.Report(new DbCloneProgressArgs(DbCloneProgressArgs.Stage.CreatingSchema, string.Empty, 0)); await cloneManager.CreateDatabaseAsync(schemaToUse).ConfigureAwait(false); if (CloneCanceled(progress, ct)) { return; } await cloneManager.Agent.ExecuteInTransactionAsync(async (cancellationToken) => { await cloneManager.DisableForeignKeysForCurrentTransactionAsync().ConfigureAwait(false); await CopyData(schemaToUse, cloneManager, progress, cancellationToken).ConfigureAwait(false); }, ct).ConfigureAwait(false); if (!ct.IsCancellationRequested) { progress?.Report( new DbCloneProgressArgs(DbCloneProgressArgs.Stage.Completed, string.Empty, 100)); } }
/// <summary> /// Copies table data from the current SqlAgent instance to the target SqlAgent instance. /// </summary> /// <param name="schema">a schema of the database to copy the data</param> /// <param name="targetManager">the target Sql schema manager to copy the data to</param> /// <remarks>Required for <see cref="CloneDatabase">CloneDatabase</see> infrastructure. /// Basicaly iterates tables, selects data, creates an IDataReader for the table and passes it to the /// <see cref="InsertTableData">InsertTableData</see> method of the target SqlAgent.</remarks> protected abstract Task CopyData(DbSchema schema, SchemaManagerBase targetManager, IProgress <DbCloneProgressArgs> progress, CancellationToken ct);
/// <summary> /// A method that should do the actual new database creation. /// </summary> /// <param name="databaseName">a name of the new database to create</param> /// <param name="dbSchema">a DbSchema to use for the new database</param> /// <remarks>After creating a new database the <see cref="CurrentDatabase">CurrentDatabase</see> /// property should be set to the new database name.</remarks> public abstract Task CreateDatabaseAsync(DbSchema dbSchema);
/// <summary> /// Gets an SQL script to create a database for the dbSchema specified. /// </summary> /// <param name="dbSchema">the database schema to get the create database script for</param> public abstract string GetCreateDatabaseSql(DbSchema dbSchema);
/// <summary> /// Compares the actualSchema definition to the gaugeSchema definition and returns /// a list of DbSchema errors, i.e. inconsistencies found and SQL statements to repair them. /// </summary> /// <param name="gaugeSchema">the gauge schema definition to compare the actualSchema against</param> /// <param name="actualSchema">the schema to check for inconsistencies (and repair)</param> public abstract List <DbSchemaError> GetDbSchemaErrors(DbSchema gaugeSchema, DbSchema actualSchema);