Exemple #1
0
        /// <summary>
        /// Be sure all tables are ready and configured for sync
        /// the ScopeSet Configuration MUST be filled by the schema form Database
        /// </summary>
        public virtual async Task <SyncContext> EnsureDatabaseAsync(SyncContext context, MessageEnsureDatabase message)
        {
            DbConnection connection = null;

            try
            {
                // Event progress
                context.SyncStage = SyncStage.DatabaseApplying;

                var script = new StringBuilder();

                // Open the connection
                using (connection = this.CreateConnection())
                {
                    await connection.OpenAsync();

                    using (var transaction = connection.BeginTransaction())
                    {
                        // Interceptor
                        var beforeArgs = new DatabaseProvisioningArgs(context, SyncProvision.All, message.Schema, connection, transaction);
                        await this.InterceptAsync(beforeArgs);

                        if (message.ScopeInfo.LastSync.HasValue && !beforeArgs.OverwriteSchema)
                        {
                            return(context);
                        }

                        // Sorting tables based on dependencies between them
                        var dmTables = message.Schema.Tables
                                       .SortByDependencies(tab => tab.ChildRelations
                                                           .Select(r => r.ChildTable));

                        foreach (var dmTable in dmTables)
                        {
                            var builder = this.GetDatabaseBuilder(dmTable);
                            // set if the builder supports creating the bulk operations proc stock
                            builder.UseBulkProcedures = this.SupportBulkOperations;

                            // adding filter
                            this.AddFilters(message.Filters, dmTable, builder);

                            context.SyncStage = SyncStage.DatabaseTableApplying;

                            // Launch any interceptor if available
                            await this.InterceptAsync(new TableProvisioningArgs(context, SyncProvision.All, dmTable, connection, transaction));

                            string currentScript = null;
                            if (beforeArgs.GenerateScript)
                            {
                                currentScript  = builder.ScriptTable(connection, transaction);
                                currentScript += builder.ScriptForeignKeys(connection, transaction);
                                script.Append(currentScript);
                            }

                            builder.Create(connection, transaction);
                            builder.CreateForeignKeys(connection, transaction);

                            // Report & Interceptor
                            context.SyncStage = SyncStage.DatabaseTableApplied;
                            var tableProvisionedArgs = new TableProvisionedArgs(context, SyncProvision.All, dmTable, connection, transaction);
                            this.ReportProgress(context, tableProvisionedArgs);
                            await this.InterceptAsync(tableProvisionedArgs);
                        }

                        // Report & Interceptor
                        context.SyncStage = SyncStage.DatabaseApplied;
                        var args = new DatabaseProvisionedArgs(context, SyncProvision.All, message.Schema, script.ToString(), connection, transaction);
                        this.ReportProgress(context, args);
                        await this.InterceptAsync(args);

                        transaction.Commit();
                    }

                    connection.Close();

                    return(context);
                }
            }
            catch (Exception ex)
            {
                throw new SyncException(ex, SyncStage.DatabaseApplying);
            }
            finally
            {
                if (connection != null && connection.State != ConnectionState.Closed)
                {
                    connection.Close();
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Be sure all tables are ready and configured for sync
        /// the ScopeSet Configuration MUST be filled by the schema form Database
        /// </summary>
        public virtual async Task <SyncContext> EnsureDatabaseAsync(SyncContext context, SyncSet schema,
                                                                    DbConnection connection, DbTransaction transaction,
                                                                    CancellationToken cancellationToken, IProgress <ProgressArgs> progress = null)
        {
            // Event progress
            context.SyncStage = SyncStage.SchemaApplying;

            var script = new StringBuilder();

            var beforeArgs = new DatabaseProvisioningArgs(context, SyncProvision.All, schema, connection, transaction);

            await this.InterceptAsync(beforeArgs).ConfigureAwait(false);

            // get Database builder
            var builder = this.GetDatabaseBuilder();

            builder.UseChangeTracking = this.UseChangeTracking;
            builder.UseBulkProcedures = this.SupportBulkOperations;

            // Initialize database if needed
            builder.EnsureDatabase(connection, transaction);

            // Sorting tables based on dependencies between them
            var schemaTables = schema.Tables
                               .SortByDependencies(tab => tab.GetRelations()
                                                   .Select(r => r.GetParentTable()));

            foreach (var schemaTable in schemaTables)
            {
                var tableBuilder = this.GetTableBuilder(schemaTable);
                // set if the builder supports creating the bulk operations proc stock
                tableBuilder.UseBulkProcedures = this.SupportBulkOperations;
                tableBuilder.UseChangeTracking = this.UseChangeTracking;

                // adding filter
                this.AddFilters(schemaTable, tableBuilder);

                context.SyncStage = SyncStage.TableSchemaApplying;

                // Launch any interceptor if available
                await this.InterceptAsync(new TableProvisioningArgs(context, SyncProvision.All, schemaTable, connection, transaction)).ConfigureAwait(false);


                tableBuilder.Create(connection, transaction);
                tableBuilder.CreateForeignKeys(connection, transaction);

                // Report & Interceptor
                context.SyncStage = SyncStage.TableSchemaApplied;
                var tableProvisionedArgs = new TableProvisionedArgs(context, SyncProvision.All, schemaTable, connection, transaction);
                this.ReportProgress(context, progress, tableProvisionedArgs);
                await this.InterceptAsync(tableProvisionedArgs).ConfigureAwait(false);
            }

            // Report & Interceptor
            context.SyncStage = SyncStage.SchemaApplied;
            var args = new DatabaseProvisionedArgs(context, SyncProvision.All, schema, script.ToString(), connection, transaction);

            this.ReportProgress(context, progress, args);
            await this.InterceptAsync(args).ConfigureAwait(false);

            await this.InterceptAsync(new TransactionCommitArgs(context, connection, transaction)).ConfigureAwait(false);

            return(context);
        }
Exemple #3
0
        /// <summary>
        /// Deprovision a database
        /// </summary>
        public async Task ProvisionAsync(SyncConfiguration configuration, SyncProvision provision)
        {
            DbConnection connection = null;

            try
            {
                if (configuration.Schema == null || !configuration.Schema.HasTables)
                {
                    throw new ArgumentNullException("tables", "You must set the tables you want to provision");
                }


                // Open the connection
                using (connection = this.CreateConnection())
                {
                    await connection.OpenAsync();

                    using (var transaction = connection.BeginTransaction())
                    {
                        // Load the configuration
                        await this.ReadSchemaAsync(configuration.Schema, connection, transaction);

                        var beforeArgs =
                            new DatabaseProvisioningArgs(null, provision, configuration.Schema, connection, transaction);

                        // Launch any interceptor if available
                        await this.InterceptAsync(beforeArgs);

                        if (provision.HasFlag(SyncProvision.Scope) || provision.HasFlag(SyncProvision.All))
                        {
                            var scopeBuilder = this.GetScopeBuilder().CreateScopeInfoBuilder(configuration.ScopeInfoTableName, connection, transaction);
                            if (scopeBuilder.NeedToCreateScopeInfoTable())
                            {
                                scopeBuilder.CreateScopeInfoTable();
                            }
                        }

                        // Sorting tables based on dependencies between them
                        var dmTables = configuration.Schema.Tables
                                       .SortByDependencies(tab => tab.ChildRelations
                                                           .Select(r => r.ChildTable));

                        foreach (var dmTable in dmTables)
                        {
                            // get the builder
                            var builder = this.GetDatabaseBuilder(dmTable);

                            // call any interceptor
                            await this.InterceptAsync(new TableProvisioningArgs(null, provision, dmTable, connection, transaction));

                            builder.UseBulkProcedures = this.SupportBulkOperations;

                            // adding filters
                            this.AddFilters(configuration.Filters, dmTable, builder);

                            // On purpose, the flag SyncProvision.All does not include the SyncProvision.Table, too dangerous...
                            if (provision.HasFlag(SyncProvision.Table))
                            {
                                builder.CreateTable(connection, transaction);
                            }

                            if (provision.HasFlag(SyncProvision.TrackingTable) || provision.HasFlag(SyncProvision.All))
                            {
                                builder.CreateTrackingTable(connection, transaction);
                            }

                            if (provision.HasFlag(SyncProvision.Triggers) || provision.HasFlag(SyncProvision.All))
                            {
                                builder.CreateTriggers(connection, transaction);
                            }

                            if (provision.HasFlag(SyncProvision.StoredProcedures) || provision.HasFlag(SyncProvision.All))
                            {
                                builder.CreateStoredProcedures(connection, transaction);
                            }

                            // call any interceptor
                            await this.InterceptAsync(new TableProvisionedArgs(null, provision, dmTable, connection, transaction));
                        }

                        // call any interceptor
                        await this.InterceptAsync(new DatabaseProvisionedArgs(null, provision, configuration.Schema, null, connection, transaction));

                        transaction.Commit();
                    }

                    connection.Close();
                }
            }
            catch (Exception ex)
            {
                throw new SyncException(ex, SyncStage.DatabaseApplying);
            }
            finally
            {
                if (connection != null && connection.State != ConnectionState.Closed)
                {
                    connection.Close();
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Deprovision a database
        /// </summary>
        public async Task ProvisionAsync(SyncSet schema, SyncProvision provision, string scopeInfoTableName = SyncOptions.DefaultScopeInfoTableName)
        {
            DbConnection  connection  = null;
            DbTransaction transaction = null;

            try
            {
                if (schema.Tables == null || !schema.HasTables)
                {
                    throw new MissingTablesException();
                }

                // Open the connection
                using (connection = this.CreateConnection())
                {
                    await connection.OpenAsync().ConfigureAwait(false);

                    // Let provider knows a connection is opened
                    this.OnConnectionOpened(connection);

                    await this.InterceptAsync(new ConnectionOpenArgs(null, connection)).ConfigureAwait(false);

                    using (transaction = connection.BeginTransaction())
                    {
                        await this.InterceptAsync(new TransactionOpenArgs(null, connection, transaction)).ConfigureAwait(false);

                        var beforeArgs =
                            new DatabaseProvisioningArgs(null, provision, schema, connection, transaction);

                        // Launch any interceptor if available
                        await this.InterceptAsync(beforeArgs).ConfigureAwait(false);

                        // get Database builder
                        var builder = this.GetDatabaseBuilder();
                        builder.UseChangeTracking = this.UseChangeTracking;
                        builder.UseBulkProcedures = this.SupportBulkOperations;

                        // Initialize database if needed
                        builder.EnsureDatabase(connection, transaction);


                        if (provision.HasFlag(SyncProvision.Scope) || provision.HasFlag(SyncProvision.All))
                        {
                            var scopeBuilder = this.GetScopeBuilder().CreateScopeInfoBuilder(scopeInfoTableName, connection, transaction);
                            if (scopeBuilder.NeedToCreateScopeInfoTable())
                            {
                                scopeBuilder.CreateScopeInfoTable();
                            }
                        }

                        // Sorting tables based on dependencies between them
                        var schemaTables = schema.Tables
                                           .SortByDependencies(tab => tab.GetRelations()
                                                               .Select(r => r.GetParentTable()));

                        foreach (var schemaTable in schemaTables)
                        {
                            // get the builder
                            var tableBuilder = this.GetTableBuilder(schemaTable);

                            // call any interceptor
                            await this.InterceptAsync(new TableProvisioningArgs(null, provision, schemaTable, connection, transaction)).ConfigureAwait(false);

                            tableBuilder.UseBulkProcedures = this.SupportBulkOperations;
                            tableBuilder.UseChangeTracking = this.UseChangeTracking;

                            // adding filters
                            this.AddFilters(schemaTable, tableBuilder);

                            // On purpose, the flag SyncProvision.All does not include the SyncProvision.Table, too dangerous...
                            if (provision.HasFlag(SyncProvision.Table))
                            {
                                tableBuilder.CreateTable(connection, transaction);
                            }

                            if (provision.HasFlag(SyncProvision.TrackingTable) || provision.HasFlag(SyncProvision.All))
                            {
                                tableBuilder.CreateTrackingTable(connection, transaction);
                            }

                            if (provision.HasFlag(SyncProvision.Triggers) || provision.HasFlag(SyncProvision.All))
                            {
                                tableBuilder.CreateTriggers(connection, transaction);
                            }

                            if (provision.HasFlag(SyncProvision.StoredProcedures) || provision.HasFlag(SyncProvision.All))
                            {
                                tableBuilder.CreateStoredProcedures(connection, transaction);
                            }

                            // call any interceptor
                            await this.InterceptAsync(new TableProvisionedArgs(null, provision, schemaTable, connection, transaction)).ConfigureAwait(false);
                        }

                        // call any interceptor
                        await this.InterceptAsync(new DatabaseProvisionedArgs(null, provision, schema, null, connection, transaction)).ConfigureAwait(false);

                        await this.InterceptAsync(new TransactionCommitArgs(null, connection, transaction)).ConfigureAwait(false);

                        transaction.Commit();
                    }

                    connection.Close();
                }
            }
            catch (Exception ex)
            {
                throw new SyncException(ex, SyncStage.SchemaApplying);
            }
            finally
            {
                if (connection != null && connection.State != ConnectionState.Closed)
                {
                    connection.Close();
                }

                await this.InterceptAsync(new ConnectionCloseArgs(null, connection, transaction)).ConfigureAwait(false);

                // Let provider knows a connection is closed
                this.OnConnectionClosed(connection);
            }
        }