GetSnapshotAsync(SyncSet schema = null, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) { // Get context or create a new one var ctx = this.GetContext(); BatchInfo serverBatchInfo = null; try { if (string.IsNullOrEmpty(this.Options.SnapshotsDirectory)) { return(0, null); } //Direction set to Download ctx.SyncWay = SyncWay.Download; if (cancellationToken.IsCancellationRequested) { cancellationToken.ThrowIfCancellationRequested(); } // Get Schema from remote provider if no schema passed from args if (schema == null) { var serverScopeInfo = await this.EnsureSchemaAsync(default, default, cancellationToken, progress).ConfigureAwait(false);
/// <summary> /// Check if a Stored Procedure exists /// </summary> /// <param name="table">A table from your Setup instance, where you want to check if the Stored Procedure exists</param> /// <param name="storedProcedureType">StoredProcedure type</param> public Task <bool> ExistStoredProcedureAsync(SetupTable table, DbStoredProcedureType storedProcedureType, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) => RunInTransactionAsync(SyncStage.None, async(ctx, connection, transaction) => { // using a fake SyncTable based on SetupTable, since we don't need columns var schemaTable = new SyncTable(table.TableName, table.SchemaName); // Create a temporary SyncSet for attaching to the schemaTable var schema = new SyncSet(); // Add this table to schema schema.Tables.Add(schemaTable); schema.EnsureSchema(); // copy filters from setup foreach (var filter in this.Setup.Filters) { schema.Filters.Add(filter); } var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup); var exists = await InternalExistsStoredProcedureAsync(ctx, tableBuilder, storedProcedureType, connection, transaction, cancellationToken, progress).ConfigureAwait(false); return(exists); }, connection, transaction, cancellationToken);
public ProvisioningArgs(SyncContext context, SyncProvision provision, SyncSet schema, DbConnection connection, DbTransaction transaction) : base(context, connection, transaction) { Provision = provision; Schema = schema; }
public DatabaseProvisionedArgs(SyncContext context, SyncProvision provision, SyncSet schema, DbConnection connection = null, DbTransaction transaction = null) : base(context, connection, transaction) { Provision = provision; Schema = schema; }
/// <summary> /// Read the schema stored from the orchestrator database, through the provider. /// </summary> /// <returns>Schema containing tables, columns, relations, primary keys</returns> public virtual Task <SyncTable> GetTableSchemaAsync(SetupTable table, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) => RunInTransactionAsync(SyncStage.SchemaReading, async(ctx, connection, transaction) => { var(schemaTable, _) = await this.InternalGetTableSchemaAsync(ctx, this.Setup, table, connection, transaction, cancellationToken, progress).ConfigureAwait(false); if (schemaTable == null) { throw new MissingTableException(table.GetFullName()); } // Create a temporary SyncSet for attaching to the schemaTable var schema = new SyncSet(); // Add this table to schema schema.Tables.Add(schemaTable); schema.EnsureSchema(); // copy filters from setup foreach (var filter in this.Setup.Filters) { schema.Filters.Add(filter); } return(schemaTable); }, connection, transaction, cancellationToken);
/// <summary> /// Create a change table with scope columns and tombstone column /// </summary> public static SyncTable CreateChangesTable(SyncTable syncTable, SyncSet owner) { if (syncTable.Schema == null) { throw new ArgumentException("Schema can't be null when creating a changes table"); } // Create an empty sync table without columns var changesTable = new SyncTable(syncTable.TableName, syncTable.SchemaName) { OriginalProvider = syncTable.OriginalProvider, SyncDirection = syncTable.SyncDirection }; // Adding primary keys foreach (var pkey in syncTable.PrimaryKeys) { changesTable.PrimaryKeys.Add(pkey); } // get ordered columns that are mutables and pkeys var orderedNames = syncTable.GetMutableColumnsWithPrimaryKeys(); foreach (var c in orderedNames) { changesTable.Columns.Add(c.Clone()); } owner.Tables.Add(changesTable); return(changesTable); }
public MigratingArgs(SyncContext context, SyncSet newSchema, SyncSetup oldSetup, SyncSetup newSetup, MigrationResults migrationResults, DbConnection connection, DbTransaction transaction) : base(context, connection, transaction) { this.NewSchema = newSchema; this.OldSetup = oldSetup; this.NewSetup = newSetup; this.MigrationResults = migrationResults; }
public SnapshotCreatingArgs(SyncContext context, SyncSet schema, string snapshotDirectory, int batchSize, long timestamp, DbConnection connection, DbTransaction transaction) : base(context, connection, transaction) { this.Schema = schema; this.SnapshotDirectory = snapshotDirectory; this.BatchSize = batchSize; this.Timestamp = timestamp; }
public bool EqualsByProperties(SyncSet otherSet) { if (otherSet == null) { return(false); } // Checking inner lists if (!this.Tables.CompareWith(otherSet.Tables)) { return(false); } if (!this.Filters.CompareWith(otherSet.Filters)) { return(false); } if (!this.Relations.CompareWith(otherSet.Relations)) { return(false); } return(true); }
/// <summary> /// Clone the SyncSet schema (without data) /// </summary> public SyncSet Clone(bool includeTables = true) { var clone = new SyncSet(); if (!includeTables) { return(clone); } foreach (var f in this.Filters) { clone.Filters.Add(f.Clone()); } foreach (var r in this.Relations) { clone.Relations.Add(r.Clone()); } foreach (var t in this.Tables) { clone.Tables.Add(t.Clone()); } // Ensure all elements has the correct ref to its parent clone.EnsureSchema(); return(clone); }
/// <summary> /// Provision the local database based on the schema parameter, and the provision enumeration /// </summary> /// <param name="schema">Schema to be applied to the database managed by the orchestrator, through the provider.</param> /// <param name="provision">Provision enumeration to determine which components to apply</param> /// <param name="clientScopeInfo">client scope. Will be saved once provision is done</param> /// <returns>Full schema with table and columns properties</returns> public virtual Task <SyncSet> ProvisionAsync(SyncSet schema, SyncProvision provision, bool overwrite = false, ScopeInfo clientScopeInfo = null, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) => RunInTransactionAsync(SyncStage.Provisioning, async(ctx, connection, transaction) => { // Check incompatibility with the flags if (provision.HasFlag(SyncProvision.ServerHistoryScope) || provision.HasFlag(SyncProvision.ServerScope)) { throw new InvalidProvisionForLocalOrchestratorException(); } // Get server scope if not supplied if (clientScopeInfo == null) { var scopeBuilder = this.GetScopeBuilder(this.Options.ScopeInfoTableName); var exists = await this.InternalExistsScopeInfoTableAsync(ctx, DbScopeType.Client, scopeBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false); if (exists) { clientScopeInfo = await this.InternalGetScopeAsync <ScopeInfo>(ctx, DbScopeType.Client, this.ScopeName, scopeBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false); } } schema = await InternalProvisionAsync(ctx, overwrite, schema, this.Setup, provision, clientScopeInfo, connection, transaction, cancellationToken, progress).ConfigureAwait(false); return(schema); }, connection, transaction, cancellationToken);
/// <summary> /// Deprovision the orchestrator database based on the Setup table argument, and the provision enumeration /// </summary> /// <param name="provision">Provision enumeration to determine which components to deprovision</param> public virtual Task DeprovisionAsync(SetupTable table, SyncProvision provision, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) { var setup = new SyncSetup(); setup.Tables.Add(table); // using a fake SyncTable based on oldSetup, since we don't need columns, but we need to have the filters var schemaTable = new SyncTable(table.TableName, table.SchemaName); // Create a temporary SyncSet for attaching to the schemaTable var tmpSchema = new SyncSet(); // Add this table to schema tmpSchema.Tables.Add(schemaTable); tmpSchema.EnsureSchema(); // copy filters from old setup foreach (var filter in this.Setup.Filters) { tmpSchema.Filters.Add(filter); } return(this.DeprovisionAsync(tmpSchema, provision, connection, transaction, cancellationToken, progress)); }
internal virtual async Task <bool> InternalUpgradeAsync(SyncContext context, SyncSet schema, ScopeInfo scopeInfo, DbScopeBuilder builder, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress <ProgressArgs> progress) { var version = SyncVersion.EnsureVersion(scopeInfo.Version); var oldVersion = version.Clone() as Version; // beta version if (version.Major == 0) { // Migrate from 0.5.x to 0.6.0 if (version.Minor <= 5) { version = await UpgdrateTo600Async(context, schema, connection, transaction, cancellationToken, progress).ConfigureAwait(false); } // Migrate from 0.6.0 to 0.6.1 if (version.Minor <= 6 && version.Build <= 0) { version = await UpgdrateTo601Async(context, schema, connection, transaction, cancellationToken, progress).ConfigureAwait(false); } } if (oldVersion != version) { scopeInfo.Version = version.ToString(); await this.InternalSaveScopeAsync(context, DbScopeType.Client, scopeInfo, builder, connection, transaction, cancellationToken, progress).ConfigureAwait(false); } return(version == SyncVersion.Current); }
public SyncRelation(string relationName, IList <SyncColumnIdentifier> columns, IList <SyncColumnIdentifier> parentColumns, SyncSet schema = null) { this.RelationName = relationName; this.ParentKeys = parentColumns; this.Keys = columns; this.Schema = schema; }
/// <summary> /// Drop all Stored Procedures /// </summary> /// <param name="table">A table from your Setup instance, where you want to drop all the Stored Procedures</param> public Task <bool> DropStoredProceduresAsync(SetupTable table, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) => RunInTransactionAsync(SyncStage.Deprovisioning, async(ctx, connection, transaction) => { var hasDroppedAtLeastOneStoredProcedure = false; // using a fake SyncTable based on SetupTable, since we don't need columns var schemaTable = new SyncTable(table.TableName, table.SchemaName); // Create a temporary SyncSet for attaching to the schemaTable var schema = new SyncSet(); // Add this table to schema schema.Tables.Add(schemaTable); schema.EnsureSchema(); // copy filters from setup foreach (var filter in this.Setup.Filters) { schema.Filters.Add(filter); } // using a fake SyncTable based on SetupTable, since we don't need columns var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup); // check bulk before hasDroppedAtLeastOneStoredProcedure = await InternalDropStoredProceduresAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false); // Removing cached commands var syncAdapter = this.GetSyncAdapter(schemaTable, this.Setup); syncAdapter.RemoveCommands(); return(hasDroppedAtLeastOneStoredProcedure); }, connection, transaction, cancellationToken);
/// <summary> /// Create all tables /// </summary> /// <param name="schema">A complete schema you want to create, containing table, primary keys and relations</param> public Task <bool> CreateTablesAsync(SyncSet schema, bool overwrite = false, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) => RunInTransactionAsync(SyncStage.Provisioning, async(ctx, connection, transaction) => { var atLeastOneHasBeenCreated = false; // Sorting tables based on dependencies between them var schemaTables = schema.Tables.SortByDependencies(tab => tab.GetRelations().Select(r => r.GetParentTable())); // if we overwritten all tables, we need to delete all of them, before recreating them if (overwrite) { foreach (var schemaTable in schemaTables.Reverse()) { var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup); var exists = await InternalExistsTableAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false); if (exists) { await InternalDropTableAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false); } } } // Then create them foreach (var schemaTable in schema.Tables) { // Get table builder var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup); var schemaExists = await InternalExistsSchemaAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false); if (!schemaExists) { await InternalCreateSchemaAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false); } var exists = await InternalExistsTableAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false); // should create only if not exists OR if overwrite has been set var shouldCreate = !exists || overwrite; if (shouldCreate) { // Drop if already exists and we need to overwrite if (exists && overwrite) { await InternalDropTableAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false); } var hasBeenCreated = await InternalCreateTableAsync(ctx, tableBuilder, connection, transaction, cancellationToken, progress).ConfigureAwait(false); if (hasBeenCreated) { atLeastOneHasBeenCreated = true; } } } return(atLeastOneHasBeenCreated); }, connection, transaction, cancellationToken);
public DatabaseProvisionedArgs(SyncContext context, SyncProvision provision, SyncSet schema, string script, DbConnection connection, DbTransaction transaction) : base(context, connection, transaction) { Provision = provision; Script = script; Schema = schema; }
/// <summary> /// Ensure filter has the correct schema (since the property is not serialized /// </summary> public void EnsureFilter(SyncSet schema) { this.Schema = schema; this.Parameters.EnsureFilters(this.Schema); this.Wheres.EnsureFilters(this.Schema); this.Joins.EnsureFilters(this.Schema); }
/// <summary> /// Gets a batch of changes to synchronize when given batch size, /// destination knowledge, and change data retriever parameters. /// </summary> /// <returns>A DbSyncContext object that will be used to retrieve the modified data.</returns> public virtual (SyncContext, BatchInfo) GetSnapshot( SyncContext context, SyncSet schema, string batchDirectory, CancellationToken cancellationToken, IProgress <ProgressArgs> progress = null) { var sb = new StringBuilder(); var underscore = ""; if (context.Parameters != null) { foreach (var p in context.Parameters.OrderBy(p => p.Name)) { var cleanValue = new string(p.Value.ToString().Where(char.IsLetterOrDigit).ToArray()); var cleanName = new string(p.Name.Where(char.IsLetterOrDigit).ToArray()); sb.Append($"{underscore}{cleanName}_{cleanValue}"); underscore = "_"; } } var directoryName = sb.ToString(); directoryName = string.IsNullOrEmpty(directoryName) ? "ALL" : directoryName; var directoryFullPath = Path.Combine(batchDirectory, directoryName); // if no snapshot present, just return null value. if (!Directory.Exists(directoryFullPath)) { return(context, null); } // Serialize on disk. var jsonConverter = new JsonConverter <BatchInfo>(); var summaryFileName = Path.Combine(directoryFullPath, "summary.json"); BatchInfo batchInfo = null; // Create the schema changeset var changesSet = new SyncSet(schema.ScopeName); // Create a Schema set without readonly columns, attached to memory changes foreach (var table in schema.Tables) { DbSyncAdapter.CreateChangesTable(schema.Tables[table.TableName, table.SchemaName], changesSet); } using (var fs = new FileStream(summaryFileName, FileMode.Open, FileAccess.Read)) { batchInfo = jsonConverter.Deserialize(fs); } batchInfo.SetSchema(changesSet); return(context, batchInfo); }
/// <summary> /// Update all untracked rows from the client database /// </summary> public virtual async Task UpdateUntrackedRowsAsync(SyncSet schema, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) { if (!this.StartTime.HasValue) { this.StartTime = DateTime.UtcNow; } // Get context or create a new one var ctx = this.GetContext(); using (var connection = this.Provider.CreateConnection()) { try { ctx.SyncStage = SyncStage.Provisioning; // If schema does not have any table, just return if (schema == null || schema.Tables == null || !schema.HasTables) { throw new MissingTablesException(); } // Open connection await this.OpenConnectionAsync(connection, cancellationToken).ConfigureAwait(false); // Create a transaction using (var transaction = connection.BeginTransaction()) { await this.InterceptAsync(new TransactionOpenedArgs(ctx, connection, transaction), cancellationToken).ConfigureAwait(false); // Update untracked rows await this.Provider.UpdateUntrackedRowsAsync(ctx, schema, this.Setup, connection, transaction, cancellationToken, progress); await this.InterceptAsync(new TransactionCommitArgs(ctx, connection, transaction), cancellationToken).ConfigureAwait(false); transaction.Commit(); } ctx.SyncStage = SyncStage.Provisioned; await this.CloseConnectionAsync(connection, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { RaiseError(ex); } finally { if (connection != null && connection.State == ConnectionState.Open) { connection.Close(); } } } }
protected virtual void Dispose(bool cleanup) { // Dispose managed ressources if (cleanup) { // clean rows this.Schema = null; } // Dispose unmanaged ressources }
private async Task <Version> UpgdrateTo601Async(SyncContext context, SyncSet schema, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress <ProgressArgs> progress) { var newVersion = new Version(0, 6, 1); // Sorting tables based on dependencies between them var schemaTables = schema.Tables .SortByDependencies(tab => tab.GetRelations() .Select(r => r.GetParentTable())); var message = $"Upgrade to {newVersion}:"; var args = new UpgradeProgressArgs(context, message, newVersion, connection, transaction); this.ReportProgress(context, progress, args, connection, transaction); foreach (var schemaTable in schemaTables) { var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup); // Upgrade Select Initial Changes var exists = await InternalExistsStoredProcedureAsync(context, tableBuilder, DbStoredProcedureType.SelectInitializedChanges, connection, transaction, cancellationToken, progress).ConfigureAwait(false); if (exists) { await InternalDropStoredProcedureAsync(context, tableBuilder, DbStoredProcedureType.SelectInitializedChanges, connection, transaction, cancellationToken, progress).ConfigureAwait(false); } await InternalCreateStoredProcedureAsync(context, tableBuilder, DbStoredProcedureType.SelectInitializedChanges, connection, transaction, cancellationToken, progress).ConfigureAwait(false); args = new UpgradeProgressArgs(context, $"SelectInitializedChanges stored procedure for table {tableBuilder.TableDescription.GetFullName()} updated", newVersion, connection, transaction); this.ReportProgress(context, progress, args, connection, transaction); // Upgrade Select Initial Changes With Filter if (tableBuilder.TableDescription.GetFilter() != null) { var existsWithFilter = await InternalExistsStoredProcedureAsync(context, tableBuilder, DbStoredProcedureType.SelectInitializedChangesWithFilters, connection, transaction, cancellationToken, progress).ConfigureAwait(false); if (existsWithFilter) { await InternalDropStoredProcedureAsync(context, tableBuilder, DbStoredProcedureType.SelectInitializedChangesWithFilters, connection, transaction, cancellationToken, progress).ConfigureAwait(false); } await InternalCreateStoredProcedureAsync(context, tableBuilder, DbStoredProcedureType.SelectInitializedChangesWithFilters, connection, transaction, cancellationToken, progress).ConfigureAwait(false); args = new UpgradeProgressArgs(context, $"SelectInitializedChangesWithFilters stored procedure for table {tableBuilder.TableDescription.GetFullName()} updated", newVersion, connection, transaction); this.ReportProgress(context, progress, args, connection, transaction); } } message = "Upgrade to 0.6.1 done."; args = new UpgradeProgressArgs(context, message, newVersion, connection, transaction); this.ReportProgress(context, progress, args, connection, transaction); return(newVersion); }
/// <summary> /// Provision the local database based on the orchestrator setup, and the provision enumeration /// </summary> /// <param name="overwrite">Overwrite existing objects</param> public virtual Task <SyncSet> ProvisionAsync(SyncSet schema = null, bool overwrite = false, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) { var provision = SyncProvision.ClientScope | SyncProvision.Table | SyncProvision.StoredProcedures | SyncProvision.Triggers | SyncProvision.TrackingTable; if (schema == null) { schema = new SyncSet(this.Setup); } return(this.ProvisionAsync(schema, provision, overwrite, null, connection, transaction, cancellationToken, progress)); }
private Task <Version> UpgdrateTo703Async(SyncContext context, SyncSet schema, SyncSetup setup, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress <ProgressArgs> progress) { var newVersion = new Version(0, 7, 3); var message = $"Upgrade to {newVersion}:"; var args = new UpgradeProgressArgs(context, message, newVersion, connection, transaction); this.ReportProgress(context, progress, args, connection, transaction); return(Task.FromResult(newVersion)); }
/// <summary> /// Ensure table as the correct schema (since the property is not serialized /// </summary> public void EnsureTable(SyncSet schema) { this.Schema = schema; if (this.Columns != null) { this.Columns.EnsureColumns(this); } if (this.Rows != null) { this.Rows.EnsureRows(this); } }
/// <summary> /// Disabling all constraints on synced tables /// Since we can disable at the database level /// Just check for one available table and execute for the whole db /// </summary> internal void DisableConstraints(SyncContext context, SyncSet schema, DbConnection connection, DbTransaction transaction = null) { if (schema == null || schema.Tables.Count <= 0) { return; } // arbitrary table var tableDescription = schema.Tables[0]; var builder = this.GetTableBuilder(tableDescription); var syncAdapter = builder.CreateSyncAdapter(connection, transaction); // disable constraints syncAdapter.DisableConstraints(); }
/// <summary> /// Delete metadatas items from tracking tables /// </summary> /// <param name="timeStampStart">Timestamp start. Used to limit the delete metadatas rows from now to this timestamp</param> /// <param name="cancellationToken">Cancellation token</param> /// <param name="progress">Progress args</param> public virtual Task <DatabaseMetadatasCleaned> DeleteMetadatasAsync(long?timeStampStart, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) => RunInTransactionAsync(SyncStage.MetadataCleaning, async(ctx, connection, transaction) => { if (!timeStampStart.HasValue) { return(null); } // Create a dummy schema to be able to call the DeprovisionAsync method on the provider // No need columns or primary keys to be able to deprovision a table SyncSet schema = new SyncSet(this.Setup); var databaseMetadatasCleaned = await this.InternalDeleteMetadatasAsync(ctx, schema, this.Setup, timeStampStart.Value, connection, transaction, cancellationToken, progress).ConfigureAwait(false); return(databaseMetadatasCleaned); }, connection, transaction, cancellationToken);
/// <summary> /// update configuration object with tables desc from server database /// </summary> internal async Task <SyncSet> InternalGetSchemaAsync(SyncContext context, SyncSetup setup, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress <ProgressArgs> progress) { if (setup == null || setup.Tables.Count <= 0) { throw new MissingTablesException(); } await this.InterceptAsync(new SchemaLoadingArgs(context, setup, connection, transaction), cancellationToken).ConfigureAwait(false); // Create the schema var schema = new SyncSet(); // copy filters from setup foreach (var filter in setup.Filters) { schema.Filters.Add(filter); } var relations = new List <DbRelationDefinition>(20); foreach (var setupTable in setup.Tables) { var(syncTable, tableRelations) = await InternalGetTableSchemaAsync(context, setup, setupTable, connection, transaction, cancellationToken, progress); // Add this table to schema schema.Tables.Add(syncTable); // Since we are not sure of the order of reading tables // create a tmp relations list relations.AddRange(tableRelations); } // Parse and affect relations to schema SetRelations(relations, schema); // Ensure all objects have correct relations to schema schema.EnsureSchema(); var schemaArgs = new SchemaLoadedArgs(context, schema, connection); await this.InterceptAsync(schemaArgs, cancellationToken).ConfigureAwait(false); this.ReportProgress(context, progress, schemaArgs); return(schema); }
/// <summary> /// Create a Stored Procedure /// </summary> /// <param name="table">A table from your Setup instance, where you want to create the Stored Procedure</param> /// <param name="storedProcedureType">StoredProcedure type</param> /// <param name="overwrite">If true, drop the existing stored procedure then create again</param> public Task <bool> CreateStoredProcedureAsync(SetupTable table, DbStoredProcedureType storedProcedureType, bool overwrite = false, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) => RunInTransactionAsync(SyncStage.Provisioning, async(ctx, connection, transaction) => { bool hasBeenCreated = false; var(schemaTable, _) = await this.InternalGetTableSchemaAsync(ctx, this.Setup, table, connection, transaction, cancellationToken, progress).ConfigureAwait(false); if (schemaTable == null) { throw new MissingTableException(table.GetFullName()); } // Create a temporary SyncSet for attaching to the schemaTable var schema = new SyncSet(); // Add this table to schema schema.Tables.Add(schemaTable); schema.EnsureSchema(); // copy filters from setup foreach (var filter in this.Setup.Filters) { schema.Filters.Add(filter); } // Get table builder var tableBuilder = this.GetTableBuilder(schemaTable, this.Setup); var exists = await InternalExistsStoredProcedureAsync(ctx, tableBuilder, storedProcedureType, connection, transaction, cancellationToken, progress).ConfigureAwait(false); // should create only if not exists OR if overwrite has been set var shouldCreate = !exists || overwrite; if (shouldCreate) { // Drop storedProcedure if already exists if (exists && overwrite) { await InternalDropStoredProcedureAsync(ctx, tableBuilder, storedProcedureType, connection, transaction, cancellationToken, progress).ConfigureAwait(false); } hasBeenCreated = await InternalCreateStoredProcedureAsync(ctx, tableBuilder, storedProcedureType, connection, transaction, cancellationToken, progress).ConfigureAwait(false); } return(hasBeenCreated); }, connection, transaction, cancellationToken);
/// <summary> /// Provision the orchestrator database based on the schema argument, and the provision enumeration /// </summary> /// <param name="schema">Schema to be applied to the database managed by the orchestrator, through the provider.</param> /// <param name="provision">Provision enumeration to determine which components to apply</param> /// <returns>Full schema with table and columns properties</returns> public virtual Task <SyncSet> ProvisionAsync(SyncSet schema, SyncProvision provision, bool overwrite = false, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null) => RunInTransactionAsync(SyncStage.Provisioning, async(ctx, connection, transaction) => { // Check incompatibility with the flags if (this is LocalOrchestrator && (provision.HasFlag(SyncProvision.ServerHistoryScope) || provision.HasFlag(SyncProvision.ServerScope))) { throw new InvalidProvisionForLocalOrchestratorException(); } else if (!(this is LocalOrchestrator) && provision.HasFlag(SyncProvision.ClientScope)) { throw new InvalidProvisionForRemoteOrchestratorException(); } schema = await InternalProvisionAsync(ctx, overwrite, schema, provision, connection, transaction, cancellationToken, progress).ConfigureAwait(false); return(schema); }, connection, transaction, cancellationToken);