InternalGetOperationAsync(ServerScopeInfo serverScopeInfo, ClientScopeInfo clientScopeInfo, SyncContext context, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress <ProgressArgs> progress)
        {
            // Create the message to be sent
            var httpMessage = new HttpMessageOperationRequest(context, clientScopeInfo);

            // serialize message
            var serializer = this.SerializerFactory.GetSerializer <HttpMessageOperationRequest>();
            var binaryData = await serializer.SerializeAsync(httpMessage);

            // No batch size submitted here, because the schema will be generated in memory and send back to the user.
            var response = await this.httpRequestHandler.ProcessRequestAsync
                               (this.HttpClient, context, this.ServiceUri, binaryData, HttpStep.GetOperation,
                               this.SerializerFactory, this.Converter, 0, this.SyncPolicy, cancellationToken, progress).ConfigureAwait(false);

            HttpMessageOperationResponse operationResponse = null;

            using (var streamResponse = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
            {
                if (streamResponse.CanRead)
                {
                    operationResponse = await this.SerializerFactory.GetSerializer <HttpMessageOperationResponse>().DeserializeAsync(streamResponse);
                }
            }

            if (operationResponse == null)
            {
                throw new ArgumentException("Http Message content for Get Operation scope can't be null");
            }

            // Return scopes and new shema
            return(context, operationResponse.SyncOperation);
        }
예제 #2
0
        public async Task <List <ServerScopeInfo> > GetAllServerScopesAsync(string scopeName, DbConnection connection, DbTransaction transaction)
        {
            var tableName = $"{scopeTableName.Unquoted().Normalized().ToString()}_server";
            List <ServerScopeInfo> scopes = new List <ServerScopeInfo>();

            var commandText =
                $@"SELECT sync_scope_name
                           , sync_scope_schema
                           , sync_scope_setup
                           , sync_scope_version
                           , sync_scope_last_clean_timestamp                    
                    FROM  `{tableName}`
                    WHERE sync_scope_name = @sync_scope_name";

            using (var command = new MySqlCommand(commandText, (MySqlConnection)connection, (MySqlTransaction)transaction))
            {
                var p = command.CreateParameter();
                p.ParameterName = "@sync_scope_name";
                p.Value         = scopeName;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                using (DbDataReader reader = await command.ExecuteReaderAsync().ConfigureAwait(false))
                {
                    if (reader.HasRows)
                    {
                        // read only the first one
                        while (reader.Read())
                        {
                            var scopeInfo = new ServerScopeInfo();
                            scopeInfo.Name    = reader["sync_scope_name"] as String;
                            scopeInfo.Schema  = reader["sync_scope_schema"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSet>((string)reader["sync_scope_schema"]);
                            scopeInfo.Setup   = reader["sync_scope_setup"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSetup>((string)reader["sync_scope_setup"]);
                            scopeInfo.Version = reader["sync_scope_version"] as string;
                            scopeInfo.LastCleanupTimestamp = reader["sync_scope_last_clean_timestamp"] != DBNull.Value ? (long)reader["sync_scope_last_clean_timestamp"] : 0L;
                            scopes.Add(scopeInfo);
                        }
                    }
                }

                return(scopes);
            }
        }
예제 #3
0
        public virtual async Task <ServerScopeInfo> InsertOrUpdateServerScopeInfoAsync(ServerScopeInfo serverScopeInfo)
        {
            var command = connection.CreateCommand();

            if (transaction != null)
            {
                command.Transaction = transaction;
            }
            bool alreadyOpened = connection.State == ConnectionState.Open;

            try
            {
                if (!alreadyOpened)
                {
                    await connection.OpenAsync().ConfigureAwait(false);
                }

                var tableName = $"{scopeTableName.Unquoted().Normalized().ToString()}_server";

                command.CommandText = $@"
                    MERGE {tableName} AS ""base"" 
                    USING (
                               SELECT  @sync_scope_name AS sync_scope_name,  
	                                   @sync_scope_schema AS sync_scope_schema,  
	                                   @sync_scope_setup AS sync_scope_setup,  
	                                   @sync_scope_version AS sync_scope_version,  
                                       @sync_scope_last_clean_timestamp AS sync_scope_last_clean_timestamp
                           ) AS ""changes"" 
                    ON ""base"".""sync_scope_name"" = ""changes"".""sync_scope_name""
                    WHEN NOT MATCHED THEN
	                    INSERT (""sync_scope_name"", ""sync_scope_schema"", ""sync_scope_setup"", ""sync_scope_version"", ""sync_scope_last_clean_timestamp"")
	                    VALUES (""changes"".""sync_scope_name"", ""changes"".""sync_scope_schema"", ""changes"".""sync_scope_setup"", ""changes"".""sync_scope_version"", ""changes"".""sync_scope_last_clean_timestamp"")
                    WHEN MATCHED THEN
	                    UPDATE SET ""sync_scope_name"" = ""changes"".""sync_scope_name"", 
                                   ""sync_scope_schema"" = ""changes"".""sync_scope_schema"", 
                                   ""sync_scope_setup"" = ""changes"".""sync_scope_setup"", 
                                   ""sync_scope_version"" = ""changes"".""sync_scope_version"", 
                                   ""sync_scope_last_clean_timestamp"" = ""changes"".""sync_scope_last_clean_timestamp""
                    OUTPUT  INSERTED.""sync_scope_name"", 
                            INSERTED.""sync_scope_schema"", 
                            INSERTED.""sync_scope_setup"", 
                            INSERTED.""sync_scope_version"", 
                            INSERTED.""sync_scope_last_clean_timestamp"";
                ";

                var p = command.CreateParameter();
                p.ParameterName = "@sync_scope_name";
                p.Value         = serverScopeInfo.Name;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_schema";
                p.Value         = serverScopeInfo.Schema == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Schema);
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_setup";
                p.Value         = serverScopeInfo.Setup == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Setup);
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_version";
                p.Value         = string.IsNullOrEmpty(serverScopeInfo.Version) ? DBNull.Value : (object)serverScopeInfo.Version;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_last_clean_timestamp";
                p.Value         = serverScopeInfo.LastCleanupTimestamp;
                p.DbType        = DbType.Int64;
                command.Parameters.Add(p);


                using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false))
                {
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            serverScopeInfo.Name    = reader["sync_scope_name"] as string;
                            serverScopeInfo.Schema  = reader["sync_scope_schema"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSet>((string)reader["sync_scope_schema"]);
                            serverScopeInfo.Setup   = reader["sync_scope_setup"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSetup>((string)reader["sync_scope_setup"]);
                            serverScopeInfo.Version = reader["sync_scope_version"] as string;
                            serverScopeInfo.LastCleanupTimestamp = reader["sync_scope_last_clean_timestamp"] != DBNull.Value ? (long)reader["sync_scope_last_clean_timestamp"] : 0;
                        }
                    }
                }

                return(serverScopeInfo);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error during CreateTableScope : {ex}");
                throw;
            }
            finally
            {
                if (!alreadyOpened && connection.State != ConnectionState.Closed)
                {
                    connection.Close();
                }

                if (command != null)
                {
                    command.Dispose();
                }
            }
        }
예제 #4
0
        public async Task <ServerScopeInfo> InsertOrUpdateServerScopeInfoAsync(ServerScopeInfo serverScopeInfo, DbConnection connection, DbTransaction transaction)
        {
            bool exist;
            var  tableName   = $"{scopeTableName.Unquoted().Normalized().ToString()}_server";
            var  commandText = $@"Select count(*) from `{tableName}` where sync_scope_name = @sync_scope_name";

            using (var command = new MySqlCommand(commandText, (MySqlConnection)connection, (MySqlTransaction)transaction))
            {
                var p = command.CreateParameter();
                p.ParameterName = "@sync_scope_name";
                p.Value         = serverScopeInfo.Name;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                exist = ((long)await command.ExecuteScalarAsync().ConfigureAwait(false)) > 0;
            }

            string stmtText = exist
                ? $"Update `{tableName}` set sync_scope_schema=@sync_scope_schema, sync_scope_setup=@sync_scope_setup, sync_scope_version=@sync_scope_version, sync_scope_last_clean_timestamp=@sync_scope_last_clean_timestamp where sync_scope_name=@sync_scope_name"
                : $"Insert into `{tableName}` (sync_scope_name, sync_scope_schema, sync_scope_setup, sync_scope_version, sync_scope_last_clean_timestamp) values (@sync_scope_name, @sync_scope_schema, @sync_scope_setup, @sync_scope_version, @sync_scope_last_clean_timestamp)";

            using (var command = new MySqlCommand(stmtText, (MySqlConnection)connection, (MySqlTransaction)transaction))
            {
                var p = command.CreateParameter();
                p.ParameterName = "@sync_scope_name";
                p.Value         = serverScopeInfo.Name;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_schema";
                p.Value         = serverScopeInfo.Schema == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Schema);
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_setup";
                p.Value         = serverScopeInfo.Setup == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Setup);
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_version";
                p.Value         = serverScopeInfo.Version;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_last_clean_timestamp";
                p.Value         = serverScopeInfo.LastCleanupTimestamp;
                p.DbType        = DbType.Int64;
                command.Parameters.Add(p);

                using (DbDataReader reader = command.ExecuteReader())
                {
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            serverScopeInfo.Name    = reader["sync_scope_name"] as string;
                            serverScopeInfo.Schema  = reader["sync_scope_schema"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSet>((string)reader["sync_scope_schema"]);
                            serverScopeInfo.Setup   = reader["sync_scope_setup"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSetup>((string)reader["sync_scope_setup"]);
                            serverScopeInfo.Version = reader["sync_scope_version"] as string;
                            serverScopeInfo.LastCleanupTimestamp = reader["sync_scope_last_clean_timestamp"] != DBNull.Value ? (long)reader["sync_scope_last_clean_timestamp"] : 0L;
                        }
                    }
                }

                return(serverScopeInfo);
            }
        }
예제 #5
0
 public Task <ServerScopeInfo> InsertOrUpdateServerScopeInfoAsync(ServerScopeInfo serverScopeInfo) => Task.FromResult(serverScopeInfo);
예제 #6
0
 /// <summary>
 /// We can't get changes from server, from a web client orchestrator
 /// </summary>
 public override Task <(long RemoteClientTimestamp, BatchInfo ServerBatchInfo, DatabaseChangesSelected ServerChangesSelected)> GetChangesAsync(ScopeInfo clientScope, ServerScopeInfo serverScope = null, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
 => throw new NotImplementedException();
 public Task <ServerScopeInfo> InsertOrUpdateServerScopeInfoAsync(ServerScopeInfo serverScopeInfo, DbConnection connection, DbTransaction transaction) => Task.FromResult(serverScopeInfo);
        public async Task <List <ServerScopeInfo> > GetAllServerScopesAsync(string scopeName)
        {
            var command = connection.CreateCommand();

            if (transaction != null)
            {
                command.Transaction = transaction;
            }

            bool alreadyOpened = connection.State == ConnectionState.Open;

            var tableName = $"{scopeTableName.Unquoted().Normalized().ToString()}_server";

            List <ServerScopeInfo> scopes = new List <ServerScopeInfo>();

            try
            {
                if (!alreadyOpened)
                {
                    await connection.OpenAsync().ConfigureAwait(false);
                }

                command.CommandText =
                    $@"SELECT sync_scope_name
                           , sync_scope_schema
                           , sync_scope_setup
                           , sync_scope_version
                           , sync_scope_last_clean_timestamp                    
                    FROM  `{tableName}`
                    WHERE sync_scope_name = @sync_scope_name";

                var p = command.CreateParameter();
                p.ParameterName = "@sync_scope_name";
                p.Value         = scopeName;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                using (DbDataReader reader = await command.ExecuteReaderAsync().ConfigureAwait(false))
                {
                    if (reader.HasRows)
                    {
                        // read only the first one
                        while (reader.Read())
                        {
                            var scopeInfo = new ServerScopeInfo();
                            scopeInfo.Name    = reader["sync_scope_name"] as String;
                            scopeInfo.Schema  = reader["sync_scope_schema"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSet>((string)reader["sync_scope_schema"]);
                            scopeInfo.Setup   = reader["sync_scope_setup"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSetup>((string)reader["sync_scope_setup"]);
                            scopeInfo.Version = reader["sync_scope_version"] as string;
                            scopeInfo.LastCleanupTimestamp = reader["sync_scope_last_clean_timestamp"] != DBNull.Value ? (long)reader["sync_scope_last_clean_timestamp"] : 0L;
                            scopes.Add(scopeInfo);
                        }
                    }
                }

                return(scopes);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error during GetAllScopes : {ex}");
                throw;
            }
            finally
            {
                if (!alreadyOpened && connection.State != ConnectionState.Closed)
                {
                    connection.Close();
                }

                if (command != null)
                {
                    command.Dispose();
                }
            }
        }
예제 #9
0
 public override Task <bool> IsOutDated(ScopeInfo clientScopeInfo, ServerScopeInfo serverScopeInfo, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
 => base.IsOutDated(clientScopeInfo, serverScopeInfo, cancellationToken, progress);
예제 #10
0
 public Task <ServerScopeInfo> InsertOrUpdateServerScopeInfoAsync(ServerScopeInfo serverScopeInfo, DbConnection connection, DbTransaction transaction) => throw new NotImplementedException();
 public Migration(ClientScopeInfo oldClientScopeInfo, ServerScopeInfo newServerScopeInfo)
 {
     this.oldClientScopeInfo = oldClientScopeInfo;
     this.newServerScopeInfo = newServerScopeInfo;
 }
        public async Task LocalOrchestrator_MultipleScopes_Check_Metadatas_Are_Deleted()
        {
            var dbName = HelperDatabase.GetRandomName("tcp_lo_");
            await HelperDatabase.CreateDatabaseAsync(ProviderType.Sql, dbName, true);

            var cs          = HelperDatabase.GetConnectionString(ProviderType.Sql, dbName);
            var sqlProvider = new SqlSyncProvider(cs);

            var ctx = new AdventureWorksContext((dbName, ProviderType.Sql, sqlProvider), true, false);
            await ctx.Database.EnsureCreatedAsync();

            var options = new SyncOptions();

            var localOrchestrator = new LocalOrchestrator(sqlProvider, options);

            var setup = new SyncSetup(this.Tables);

            var setup2 = new SyncSetup(this.Tables);

            setup2.Filters.Add("Customer", "EmployeeID");

            var schema = await localOrchestrator.GetSchemaAsync(setup);

            var localScopeInfo1 = await localOrchestrator.GetClientScopeInfoAsync();

            var localScopeInfo2 = await localOrchestrator.GetClientScopeInfoAsync("A");

            var serverScope1 = new ServerScopeInfo
            {
                Name    = localScopeInfo1.Name,
                Schema  = schema,
                Setup   = setup,
                Version = localScopeInfo1.Version
            };

            var serverScope2 = new ServerScopeInfo
            {
                Name    = localScopeInfo2.Name,
                Schema  = schema,
                Setup   = setup2,
                Version = localScopeInfo2.Version
            };

            // Provision two scopes (already tested in previous test)
            localScopeInfo1 = await localOrchestrator.ProvisionAsync(serverScope1);

            localScopeInfo2 = await localOrchestrator.ProvisionAsync(serverScope2);

            Assert.NotNull(localScopeInfo1.Setup);
            Assert.NotNull(localScopeInfo1.Schema);

            Assert.NotNull(localScopeInfo2.Setup);
            Assert.NotNull(localScopeInfo2.Schema);


            // Deprovision
            await localOrchestrator.DeprovisionAsync("A");

            foreach (var table in localScopeInfo1.Setup.Tables)
            {
                var tableName  = table.TableName;
                var schemaName = table.SchemaName;

                foreach (var objectSpType in Enum.GetValues(typeof(Builders.DbStoredProcedureType)))
                {
                    var spType = (Builders.DbStoredProcedureType)objectSpType;

                    var exists1 = await localOrchestrator.ExistStoredProcedureAsync(
                        localScopeInfo1, tableName, schemaName, spType);

                    var exists2 = await localOrchestrator.ExistStoredProcedureAsync(
                        localScopeInfo2, tableName, schemaName, spType);


                    if (spType == Builders.DbStoredProcedureType.SelectChangesWithFilters ||
                        spType == Builders.DbStoredProcedureType.SelectInitializedChangesWithFilters)
                    {
                        Assert.False(exists1);
                    }
                    else
                    {
                        Assert.True(exists1);
                    }

                    Assert.False(exists2);
                }

                foreach (var objectSpType in Enum.GetValues(typeof(Builders.DbTriggerType)))
                {
                    var trigType = (Builders.DbTriggerType)objectSpType;

                    var existsTrig1 = await localOrchestrator.ExistTriggerAsync(localScopeInfo1, tableName, schemaName, trigType);

                    var existsTrig2 = await localOrchestrator.ExistTriggerAsync(localScopeInfo2, tableName, schemaName, trigType);

                    Assert.False(existsTrig1);
                    Assert.False(existsTrig2);
                }

                var trackTableExists1 = await localOrchestrator.ExistTrackingTableAsync(localScopeInfo1, tableName, schemaName);

                var trackTableExists2 = await localOrchestrator.ExistTrackingTableAsync(localScopeInfo2, tableName, schemaName);

                // Tracking table are still existing for others scopes
                Assert.True(trackTableExists1);
                Assert.True(trackTableExists2);
            }

            // Deprovision
            await localOrchestrator.DeprovisionAsync();

            foreach (var table in localScopeInfo1.Setup.Tables)
            {
                var tableName  = table.TableName;
                var schemaName = table.SchemaName;

                foreach (var objectSpType in Enum.GetValues(typeof(Builders.DbStoredProcedureType)))
                {
                    var spType = (Builders.DbStoredProcedureType)objectSpType;

                    var exists1 = await localOrchestrator.ExistStoredProcedureAsync(
                        localScopeInfo1, tableName, schemaName, spType);

                    var exists2 = await localOrchestrator.ExistStoredProcedureAsync(
                        localScopeInfo2, tableName, schemaName, spType);

                    Assert.False(exists1);
                    Assert.False(exists2);
                }
            }


            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public override async Task <ServerScopeInfo> InsertOrUpdateServerScopeInfoAsync(ServerScopeInfo serverScopeInfo, DbConnection connection, DbTransaction transaction)
        {
            var tableName   = $"{scopeTableName.Unquoted().Normalized().ToString()}_server";
            var commandText = $@"
                    Declare @minVersion int;
                    Select @minVersion = MIN(CHANGE_TRACKING_MIN_VALID_VERSION(T.object_id)) from sys.tables T where CHANGE_TRACKING_MIN_VALID_VERSION(T.object_id) is not null;

                    MERGE {tableName} AS [base] 
                    USING (
                               SELECT  @sync_scope_name AS sync_scope_name,  
	                                   @sync_scope_schema AS sync_scope_schema,  
	                                   @sync_scope_setup AS sync_scope_setup,  
	                                   @sync_scope_version AS sync_scope_version
                           ) AS [changes] 
                    ON [base].[sync_scope_name] = [changes].[sync_scope_name]
                    WHEN NOT MATCHED THEN
	                    INSERT ([sync_scope_name], [sync_scope_schema], [sync_scope_setup], [sync_scope_version], [sync_scope_last_clean_timestamp])
	                    VALUES ([changes].[sync_scope_name], [changes].[sync_scope_schema], [changes].[sync_scope_setup], [changes].[sync_scope_version], @minVersion)
                    WHEN MATCHED THEN
	                    UPDATE SET [sync_scope_name] = [changes].[sync_scope_name], 
                                   [sync_scope_schema] = [changes].[sync_scope_schema], 
                                   [sync_scope_setup] = [changes].[sync_scope_setup], 
                                   [sync_scope_version] = [changes].[sync_scope_version], 
                                   [sync_scope_last_clean_timestamp] = @minVersion
                    OUTPUT  INSERTED.[sync_scope_name], 
                            INSERTED.[sync_scope_schema], 
                            INSERTED.[sync_scope_setup], 
                            INSERTED.[sync_scope_version], 
                            INSERTED.[sync_scope_last_clean_timestamp];
                ";

            using (var command = new SqlCommand(commandText, (SqlConnection)connection, (SqlTransaction)transaction))
            {
                var p = command.CreateParameter();
                p.ParameterName = "@sync_scope_name";
                p.Value         = serverScopeInfo.Name;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_schema";
                p.Value         = serverScopeInfo.Schema == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Schema);
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_setup";
                p.Value         = serverScopeInfo.Setup == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Setup);
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_version";
                p.Value         = string.IsNullOrEmpty(serverScopeInfo.Version) ? DBNull.Value : (object)serverScopeInfo.Version;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                //p = command.CreateParameter();
                //p.ParameterName = "@sync_scope_last_clean_timestamp";
                //p.Value = serverScopeInfo.LastCleanupTimestamp;
                //p.DbType = DbType.Int64;
                //command.Parameters.Add(p);


                using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false))
                {
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            serverScopeInfo.Name    = reader["sync_scope_name"] as string;
                            serverScopeInfo.Schema  = reader["sync_scope_schema"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSet>((string)reader["sync_scope_schema"]);
                            serverScopeInfo.Setup   = reader["sync_scope_setup"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSetup>((string)reader["sync_scope_setup"]);
                            serverScopeInfo.Version = reader["sync_scope_version"] as string;
                            serverScopeInfo.LastCleanupTimestamp = reader["sync_scope_last_clean_timestamp"] != DBNull.Value ? (long)reader["sync_scope_last_clean_timestamp"] : 0;
                        }
                    }
                }

                return(serverScopeInfo);
            }
        }
        public override async Task <ServerScopeInfo> InsertOrUpdateServerScopeInfoAsync(ServerScopeInfo serverScopeInfo)
        {
            var command = connection.CreateCommand();

            if (transaction != null)
            {
                command.Transaction = transaction;
            }
            bool alreadyOpened = connection.State == ConnectionState.Open;

            try
            {
                if (!alreadyOpened)
                {
                    await connection.OpenAsync().ConfigureAwait(false);
                }

                var tableName = $"{scopeTableName.Unquoted().Normalized().ToString()}_server";

                command.CommandText = $@"
                    Declare @minVersion int;
                    Select @minVersion = MIN(CHANGE_TRACKING_MIN_VALID_VERSION(T.object_id)) from sys.tables T where CHANGE_TRACKING_MIN_VALID_VERSION(T.object_id) is not null;

                    MERGE {tableName} AS [base] 
                    USING (
                               SELECT  @sync_scope_name AS sync_scope_name,  
	                                   @sync_scope_schema AS sync_scope_schema,  
	                                   @sync_scope_setup AS sync_scope_setup,  
	                                   @sync_scope_version AS sync_scope_version
                           ) AS [changes] 
                    ON [base].[sync_scope_name] = [changes].[sync_scope_name]
                    WHEN NOT MATCHED THEN
	                    INSERT ([sync_scope_name], [sync_scope_schema], [sync_scope_setup], [sync_scope_version], [sync_scope_last_clean_timestamp])
	                    VALUES ([changes].[sync_scope_name], [changes].[sync_scope_schema], [changes].[sync_scope_setup], [changes].[sync_scope_version], @minVersion)
                    WHEN MATCHED THEN
	                    UPDATE SET [sync_scope_name] = [changes].[sync_scope_name], 
                                   [sync_scope_schema] = [changes].[sync_scope_schema], 
                                   [sync_scope_setup] = [changes].[sync_scope_setup], 
                                   [sync_scope_version] = [changes].[sync_scope_version], 
                                   [sync_scope_last_clean_timestamp] = @minVersion
                    OUTPUT  INSERTED.[sync_scope_name], 
                            INSERTED.[sync_scope_schema], 
                            INSERTED.[sync_scope_setup], 
                            INSERTED.[sync_scope_version], 
                            INSERTED.[sync_scope_last_clean_timestamp];
                ";

                var p = command.CreateParameter();
                p.ParameterName = "@sync_scope_name";
                p.Value         = serverScopeInfo.Name;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_schema";
                p.Value         = serverScopeInfo.Schema == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Schema);
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_setup";
                p.Value         = serverScopeInfo.Setup == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Setup);
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_version";
                p.Value         = string.IsNullOrEmpty(serverScopeInfo.Version) ? DBNull.Value : (object)serverScopeInfo.Version;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                //p = command.CreateParameter();
                //p.ParameterName = "@sync_scope_last_clean_timestamp";
                //p.Value = serverScopeInfo.LastCleanupTimestamp;
                //p.DbType = DbType.Int64;
                //command.Parameters.Add(p);


                using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false))
                {
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            serverScopeInfo.Name    = reader["sync_scope_name"] as string;
                            serverScopeInfo.Schema  = reader["sync_scope_schema"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSet>((string)reader["sync_scope_schema"]);
                            serverScopeInfo.Setup   = reader["sync_scope_setup"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSetup>((string)reader["sync_scope_setup"]);
                            serverScopeInfo.Version = reader["sync_scope_version"] as string;
                            serverScopeInfo.LastCleanupTimestamp = reader["sync_scope_last_clean_timestamp"] != DBNull.Value ? (long)reader["sync_scope_last_clean_timestamp"] : 0;
                        }
                    }
                }

                return(serverScopeInfo);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error during CreateTableScope : {ex}");
                throw;
            }
            finally
            {
                if (!alreadyOpened && connection.State != ConnectionState.Closed)
                {
                    connection.Close();
                }

                if (command != null)
                {
                    command.Dispose();
                }
            }
        }
예제 #15
0
        public async Task <List <ServerScopeInfo> > GetAllServerScopesAsync(string scopeName)
        {
            using (var command = connection.CreateCommand())
            {
                var tableName = $"{scopeTableName.Unquoted().Normalized().ToString()}_server";

                if (transaction != null)
                {
                    command.Transaction = transaction;
                }

                bool alreadyOpened = connection.State == ConnectionState.Open;

                var scopes = new List <ServerScopeInfo>();

                if (!alreadyOpened)
                {
                    await connection.OpenAsync().ConfigureAwait(false);
                }

                command.CommandText =
                    $@"SELECT ""sync_scope_name""
                           , ""sync_scope_schema""
                           , ""sync_scope_setup""
                           , ""sync_scope_version""
                           , ""sync_scope_last_clean_timestamp""
                    FROM  ""{tableName}""
                    WHERE ""sync_scope_name"" = @sync_scope_name";

                var p = command.CreateParameter();
                p.ParameterName = "@sync_scope_name";
                p.Value         = scopeName;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false))
                {
                    if (reader.HasRows)
                    {
                        // read only the first one
                        while (reader.Read())
                        {
                            var serverScopeInfo = new ServerScopeInfo();
                            serverScopeInfo.Name    = reader["sync_scope_name"] as string;
                            serverScopeInfo.Schema  = reader["sync_scope_schema"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSet>((string)reader["sync_scope_schema"]);
                            serverScopeInfo.Setup   = reader["sync_scope_setup"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSetup>((string)reader["sync_scope_setup"]);
                            serverScopeInfo.Version = reader["sync_scope_version"] as string;
                            serverScopeInfo.LastCleanupTimestamp = reader["sync_scope_last_clean_timestamp"] != DBNull.Value ? (long)reader["sync_scope_last_clean_timestamp"] : 0;
                            scopes.Add(serverScopeInfo);
                        }
                    }
                }

                if (!alreadyOpened && connection.State != ConnectionState.Closed)
                {
                    connection.Close();
                }

                return(scopes);
            }
        }
예제 #16
0
        InternalGetSnapshotAsync(ServerScopeInfo serverScopeInfo, SyncContext context, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
        {
            await using var runner = await this.GetConnectionAsync(context, SyncMode.Reading, SyncStage.ScopeLoading, connection, transaction, cancellationToken, progress).ConfigureAwait(false);

            // Make a remote call to get Schema from remote provider
            if (serverScopeInfo.Schema == null)
            {
                (context, serverScopeInfo) = await this.InternalGetServerScopeInfoAsync(
                    context, null, false, runner.Connection, runner.Transaction, runner.CancellationToken, runner.Progress).ConfigureAwait(false);

                serverScopeInfo.Schema.EnsureSchema();
            }

            // Generate a batch directory
            var batchDirectoryRoot     = this.Options.BatchDirectory;
            var batchDirectoryName     = string.Concat(DateTime.UtcNow.ToString("yyyy_MM_dd_ss"), Path.GetRandomFileName().Replace(".", ""));
            var batchDirectoryFullPath = Path.Combine(batchDirectoryRoot, batchDirectoryName);

            if (!Directory.Exists(batchDirectoryFullPath))
            {
                Directory.CreateDirectory(batchDirectoryFullPath);
            }

            // Create the BatchInfo serialized (forced because in a snapshot call, so we are obviously serialized on disk)
            var serverBatchInfo = new BatchInfo(serverScopeInfo.Schema, batchDirectoryRoot, batchDirectoryName);

            // Firstly, get the snapshot summary
            var changesToSend = new HttpMessageSendChangesRequest(context, null);
            var serializer    = this.SerializerFactory.GetSerializer <HttpMessageSendChangesRequest>();
            var binaryData    = await serializer.SerializeAsync(changesToSend);

            var response0 = await this.httpRequestHandler.ProcessRequestAsync(
                this.HttpClient, context, this.ServiceUri, binaryData, HttpStep.GetSummary,
                this.SerializerFactory, this.Converter, 0, this.SyncPolicy, cancellationToken, progress).ConfigureAwait(false);

            HttpMessageSummaryResponse summaryResponseContent = null;

            using (var streamResponse = await response0.Content.ReadAsStreamAsync().ConfigureAwait(false))
            {
                var responseSerializer = this.SerializerFactory.GetSerializer <HttpMessageSummaryResponse>();

                if (streamResponse.CanRead)
                {
                    summaryResponseContent = await responseSerializer.DeserializeAsync(streamResponse);

                    serverBatchInfo.RowsCount = summaryResponseContent.BatchInfo?.RowsCount ?? 0;

                    if (summaryResponseContent.BatchInfo?.BatchPartsInfo != null)
                    {
                        foreach (var bpi in summaryResponseContent.BatchInfo.BatchPartsInfo)
                        {
                            serverBatchInfo.BatchPartsInfo.Add(bpi);
                        }
                    }
                }
            }

            if (summaryResponseContent == null)
            {
                throw new Exception("Summary can't be null");
            }

            context = summaryResponseContent.SyncContext;

            // no snapshot
            if ((serverBatchInfo.BatchPartsInfo == null || serverBatchInfo.BatchPartsInfo.Count <= 0) && serverBatchInfo.RowsCount <= 0)
            {
                return(context, 0, null, new DatabaseChangesSelected());
            }

            // If we have a snapshot we are raising the batches downloading process that will occurs
            await this.InterceptAsync(new HttpBatchesDownloadingArgs(context, serverBatchInfo, this.GetServiceHost()), progress, cancellationToken).ConfigureAwait(false);

            await serverBatchInfo.BatchPartsInfo.ForEachAsync(async bpi =>
            {
                var changesToSend3 = new HttpMessageGetMoreChangesRequest(context, bpi.Index);
                var serializer3    = this.SerializerFactory.GetSerializer <HttpMessageGetMoreChangesRequest>();
                var binaryData3    = await serializer3.SerializeAsync(changesToSend3);

                await this.InterceptAsync(new HttpGettingServerChangesRequestArgs(bpi.Index, serverBatchInfo.BatchPartsInfo.Count, summaryResponseContent.SyncContext, this.GetServiceHost()), progress, cancellationToken).ConfigureAwait(false);

                var response = await this.httpRequestHandler.ProcessRequestAsync(
                    this.HttpClient, context, this.ServiceUri, binaryData3, HttpStep.GetMoreChanges,
                    this.SerializerFactory, this.Converter, 0, this.SyncPolicy, cancellationToken, progress).ConfigureAwait(false);

                if (this.SerializerFactory.Key != "json")
                {
                    var s = this.SerializerFactory.GetSerializer <HttpMessageSendChangesResponse>();
                    using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
                    var getMoreChanges       = await s.DeserializeAsync(responseStream);

                    if (getMoreChanges != null && getMoreChanges.Changes != null && getMoreChanges.Changes.HasRows)
                    {
                        var localSerializer = new LocalJsonSerializer();

                        var interceptorsWriting = this.interceptors.GetInterceptors <SerializingRowArgs>();
                        if (interceptorsWriting.Count > 0)
                        {
                            localSerializer.OnWritingRow(async(syncTable, rowArray) =>
                            {
                                var args = new SerializingRowArgs(context, syncTable, rowArray);
                                await this.InterceptAsync(args, progress, cancellationToken).ConfigureAwait(false);
                                return(args.Result);
                            });
                        }
                        // Should have only one table
                        var table       = getMoreChanges.Changes.Tables[0];
                        var schemaTable = DbSyncAdapter.CreateChangesTable(serverScopeInfo.Schema.Tables[table.TableName, table.SchemaName]);

                        var fullPath = Path.Combine(batchDirectoryFullPath, bpi.FileName);

                        // open the file and write table header
                        await localSerializer.OpenFileAsync(fullPath, schemaTable).ConfigureAwait(false);

                        foreach (var row in table.Rows)
                        {
                            await localSerializer.WriteRowToFileAsync(new SyncRow(schemaTable, row), schemaTable).ConfigureAwait(false);
                        }

                        // Close file
                        await localSerializer.CloseFileAsync(fullPath, schemaTable).ConfigureAwait(false);
                    }
                }
                else
                {
                    // Serialize
                    await SerializeAsync(response, bpi.FileName, batchDirectoryFullPath, this).ConfigureAwait(false);
                }


                // Raise response from server containing a batch changes
                await this.InterceptAsync(new HttpGettingServerChangesResponseArgs(serverBatchInfo, bpi.Index, bpi.RowsCount, summaryResponseContent.SyncContext, this.GetServiceHost()), progress, cancellationToken).ConfigureAwait(false);
            });

            await this.InterceptAsync(new HttpBatchesDownloadedArgs(summaryResponseContent, summaryResponseContent.SyncContext, this.GetServiceHost()), progress, cancellationToken).ConfigureAwait(false);

            return(context, summaryResponseContent.RemoteClientTimestamp, serverBatchInfo, summaryResponseContent.ServerChangesSelected);
        }
예제 #17
0
        public virtual async Task <ServerScopeInfo> InsertOrUpdateServerScopeInfoAsync(ServerScopeInfo serverScopeInfo, DbConnection connection, DbTransaction transaction)
        {
            var tableName   = $"{scopeTableName.Unquoted().Normalized().ToString()}_server";
            var commandText = $@"
                    MERGE {tableName} AS ""base"" 
                    USING (
                               SELECT  @sync_scope_name AS sync_scope_name,  
	                                   @sync_scope_schema AS sync_scope_schema,  
	                                   @sync_scope_setup AS sync_scope_setup,  
	                                   @sync_scope_version AS sync_scope_version,  
                                       @sync_scope_last_clean_timestamp AS sync_scope_last_clean_timestamp
                           ) AS ""changes"" 
                    ON ""base"".""sync_scope_name"" = ""changes"".""sync_scope_name""
                    WHEN NOT MATCHED THEN
	                    INSERT (""sync_scope_name"", ""sync_scope_schema"", ""sync_scope_setup"", ""sync_scope_version"", ""sync_scope_last_clean_timestamp"")
	                    VALUES (""changes"".""sync_scope_name"", ""changes"".""sync_scope_schema"", ""changes"".""sync_scope_setup"", ""changes"".""sync_scope_version"", ""changes"".""sync_scope_last_clean_timestamp"")
                    WHEN MATCHED THEN
	                    UPDATE SET ""sync_scope_name"" = ""changes"".""sync_scope_name"", 
                                   ""sync_scope_schema"" = ""changes"".""sync_scope_schema"", 
                                   ""sync_scope_setup"" = ""changes"".""sync_scope_setup"", 
                                   ""sync_scope_version"" = ""changes"".""sync_scope_version"", 
                                   ""sync_scope_last_clean_timestamp"" = ""changes"".""sync_scope_last_clean_timestamp""
                    OUTPUT  INSERTED.""sync_scope_name"", 
                            INSERTED.""sync_scope_schema"", 
                            INSERTED.""sync_scope_setup"", 
                            INSERTED.""sync_scope_version"", 
                            INSERTED.""sync_scope_last_clean_timestamp"";
                ";

            using (var command = new NpgsqlCommand(commandText, (NpgsqlConnection)connection, (NpgsqlTransaction)transaction))
            {
                var p = command.CreateParameter();
                p.ParameterName = "@sync_scope_name";
                p.Value         = serverScopeInfo.Name;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_schema";
                p.Value         = serverScopeInfo.Schema == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Schema);
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_setup";
                p.Value         = serverScopeInfo.Setup == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Setup);
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_version";
                p.Value         = string.IsNullOrEmpty(serverScopeInfo.Version) ? DBNull.Value : (object)serverScopeInfo.Version;
                p.DbType        = DbType.String;
                command.Parameters.Add(p);

                p = command.CreateParameter();
                p.ParameterName = "@sync_scope_last_clean_timestamp";
                p.Value         = serverScopeInfo.LastCleanupTimestamp;
                p.DbType        = DbType.Int64;
                command.Parameters.Add(p);


                using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false))
                {
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            serverScopeInfo.Name    = reader["sync_scope_name"] as string;
                            serverScopeInfo.Schema  = reader["sync_scope_schema"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSet>((string)reader["sync_scope_schema"]);
                            serverScopeInfo.Setup   = reader["sync_scope_setup"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSetup>((string)reader["sync_scope_setup"]);
                            serverScopeInfo.Version = reader["sync_scope_version"] as string;
                            serverScopeInfo.LastCleanupTimestamp = reader["sync_scope_last_clean_timestamp"] != DBNull.Value ? (long)reader["sync_scope_last_clean_timestamp"] : 0;
                        }
                    }
                }

                return(serverScopeInfo);
            }
        }
예제 #18
0
 public Task <ServerScopeInfo> InsertOrUpdateServerScopeInfoAsync(ServerScopeInfo serverScopeInfo) => throw new NotImplementedException();
        public async Task <ServerScopeInfo> InsertOrUpdateServerScopeInfoAsync(ServerScopeInfo serverScopeInfo)
        {
            bool alreadyOpened = connection.State == ConnectionState.Open;
            bool exist;
            var  tableName = $"{scopeTableName.Unquoted().Normalized().ToString()}_server";

            try
            {
                using (var command = connection.CreateCommand())
                {
                    if (transaction != null)
                    {
                        command.Transaction = transaction;
                    }

                    if (!alreadyOpened)
                    {
                        await connection.OpenAsync().ConfigureAwait(false);
                    }

                    command.CommandText = $@"Select count(*) from `{tableName}` where sync_scope_name = @sync_scope_name";

                    var p = command.CreateParameter();
                    p.ParameterName = "@sync_scope_name";
                    p.Value         = serverScopeInfo.Name;
                    p.DbType        = DbType.String;
                    command.Parameters.Add(p);

                    exist = ((long)await command.ExecuteScalarAsync().ConfigureAwait(false)) > 0;
                }

                string stmtText = exist
                    ? $"Update `{tableName}` set sync_scope_schema=@sync_scope_schema, sync_scope_setup=@sync_scope_setup, sync_scope_version=@sync_scope_version, sync_scope_last_clean_timestamp=@sync_scope_last_clean_timestamp where sync_scope_name=@sync_scope_name"
                    : $"Insert into `{tableName}` (sync_scope_name, sync_scope_schema, sync_scope_setup, sync_scope_version, sync_scope_last_clean_timestamp) values (@sync_scope_name, @sync_scope_schema, @sync_scope_setup, @sync_scope_version, @sync_scope_last_clean_timestamp)";

                using (var command = connection.CreateCommand())
                {
                    if (transaction != null)
                    {
                        command.Transaction = transaction;
                    }

                    command.CommandText = stmtText;

                    var p = command.CreateParameter();
                    p.ParameterName = "@sync_scope_name";
                    p.Value         = serverScopeInfo.Name;
                    p.DbType        = DbType.String;
                    command.Parameters.Add(p);

                    p = command.CreateParameter();
                    p.ParameterName = "@sync_scope_schema";
                    p.Value         = serverScopeInfo.Schema == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Schema);
                    p.DbType        = DbType.String;
                    command.Parameters.Add(p);

                    p = command.CreateParameter();
                    p.ParameterName = "@sync_scope_setup";
                    p.Value         = serverScopeInfo.Setup == null ? DBNull.Value : (object)JsonConvert.SerializeObject(serverScopeInfo.Setup);
                    p.DbType        = DbType.String;
                    command.Parameters.Add(p);

                    p = command.CreateParameter();
                    p.ParameterName = "@sync_scope_version";
                    p.Value         = serverScopeInfo.Version;
                    p.DbType        = DbType.String;
                    command.Parameters.Add(p);

                    p = command.CreateParameter();
                    p.ParameterName = "@sync_scope_last_clean_timestamp";
                    p.Value         = serverScopeInfo.LastCleanupTimestamp;
                    p.DbType        = DbType.Int64;
                    command.Parameters.Add(p);

                    using (DbDataReader reader = command.ExecuteReader())
                    {
                        if (reader.HasRows)
                        {
                            while (reader.Read())
                            {
                                serverScopeInfo.Name    = reader["sync_scope_name"] as string;
                                serverScopeInfo.Schema  = reader["sync_scope_schema"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSet>((string)reader["sync_scope_schema"]);
                                serverScopeInfo.Setup   = reader["sync_scope_setup"] == DBNull.Value ? null : JsonConvert.DeserializeObject <SyncSetup>((string)reader["sync_scope_setup"]);
                                serverScopeInfo.Version = reader["sync_scope_version"] as string;
                                serverScopeInfo.LastCleanupTimestamp = reader["sync_scope_last_clean_timestamp"] != DBNull.Value ? (long)reader["sync_scope_last_clean_timestamp"] : 0L;
                            }
                        }
                    }

                    return(serverScopeInfo);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error during InsertOrUpdateServerScopeInfoAsync : {ex}");
                throw;
            }
            finally
            {
                if (!alreadyOpened && connection.State != ConnectionState.Closed)
                {
                    connection.Close();
                }
            }
        }
 public override Task <ServerScopeInfo> SaveServerScopeInfoAsync(ServerScopeInfo serverScopeInfo, DbConnection connection = null, DbTransaction transaction = null, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
 => throw new NotImplementedException();
예제 #21
0
 public override Task <ServerScopeInfo> ProvisionAsync(ServerScopeInfo serverScopeInfo, SyncProvision provision = default, bool overwrite = false, DbConnection connection = default, DbTransaction transaction = default, CancellationToken cancellationToken = default, IProgress <ProgressArgs> progress = null)
 => throw new NotImplementedException();
예제 #22
0
        public async Task Scenario_Using_ExistingClientDatabase_ProvisionDeprovision_WithoutAccessToServerSide(SyncOptions options)
        {
            // This test works only if we have the same exact provider on both sides

            // create client orchestrator that is the same as server
            var clientDatabaseName = HelperDatabase.GetRandomName("tcpfilt_cli_");
            var clientProvider     = this.CreateProvider(this.ServerType, clientDatabaseName);

            var client = (clientDatabaseName, Server.ProviderType, Provider : clientProvider);

            // create a client schema without seeding
            await this.EnsureDatabaseSchemaAndSeedAsync(client, false, UseFallbackSchema);

            // Since we don't have access to remote orchestrator,
            // we can simulate a server scope
            var localOrchestrator = new LocalOrchestrator(client.Provider, options);

            // Get the local scope
            var localScopeInfo = await localOrchestrator.GetClientScopeInfoAsync();

            // getting local scope did not get the schema
            var schema = await localOrchestrator.GetSchemaAsync(this.FilterSetup);

            // getting local schema from these provider will not fill the schema name for each table
            // and we need the exact same name even if it's not used on client
            if (client.ProviderType == ProviderType.MySql || client.ProviderType == ProviderType.MariaDB || client.ProviderType == ProviderType.Sqlite)
            {
                foreach (var table in schema.Tables)
                {
                    var setupTable = this.FilterSetup.Tables.First(t => t.TableName == table.TableName);
                    table.SchemaName = setupTable.SchemaName;
                }
            }

            // Simulate a server scope
            var serverScope = new ServerScopeInfo
            {
                Name    = localScopeInfo.Name,
                Schema  = schema,
                Setup   = this.FilterSetup,
                Version = localScopeInfo.Version
            };

            // just check interceptor
            var onTableCreatedCount = 0;

            localOrchestrator.OnTableCreated(args => onTableCreatedCount++);

            // Provision the database with all tracking tables, stored procedures, triggers and scope
            var clientScope = await localOrchestrator.ProvisionAsync(serverScope);

            //--------------------------
            // ASSERTION
            //--------------------------

            // check if scope table is correctly created
            var scopeInfoTableExists = await localOrchestrator.ExistScopeInfoTableAsync(clientScope.Name, DbScopeType.Client);

            Assert.True(scopeInfoTableExists);

            // get the db manager
            foreach (var setupTable in this.FilterSetup.Tables)
            {
                Assert.True(await localOrchestrator.ExistTrackingTableAsync(clientScope, setupTable.TableName, setupTable.SchemaName));

                Assert.True(await localOrchestrator.ExistTriggerAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbTriggerType.Delete));
                Assert.True(await localOrchestrator.ExistTriggerAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbTriggerType.Insert));
                Assert.True(await localOrchestrator.ExistTriggerAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbTriggerType.Update));

                if (client.ProviderType == ProviderType.Sql)
                {
                    Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.BulkDeleteRows));
                    Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.BulkTableType));
                    Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.BulkUpdateRows));
                }

                Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.DeleteMetadata));
                Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.DeleteRow));
                Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.Reset));
                Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.SelectChanges));
                Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.SelectInitializedChanges));
                Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.SelectRow));
                Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.UpdateRow));

                // Filters here
                Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.SelectChangesWithFilters));
                Assert.True(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.SelectInitializedChangesWithFilters));
            }

            //localOrchestrator.OnTableProvisioned(null);

            //// Deprovision the database with all tracking tables, stored procedures, triggers and scope
            await localOrchestrator.DeprovisionAsync(SyncProvision.StoredProcedures | SyncProvision.Triggers | SyncProvision.ClientScope | SyncProvision.TrackingTable);

            // check if scope table is correctly created
            scopeInfoTableExists = await localOrchestrator.ExistScopeInfoTableAsync(clientScope.Name, DbScopeType.Client);

            Assert.False(scopeInfoTableExists);

            // get the db manager
            foreach (var setupTable in this.FilterSetup.Tables)
            {
                Assert.False(await localOrchestrator.ExistTrackingTableAsync(clientScope, setupTable.TableName, setupTable.SchemaName));

                Assert.False(await localOrchestrator.ExistTriggerAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbTriggerType.Delete));
                Assert.False(await localOrchestrator.ExistTriggerAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbTriggerType.Insert));
                Assert.False(await localOrchestrator.ExistTriggerAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbTriggerType.Update));

                if (client.ProviderType == ProviderType.Sql)
                {
                    Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.BulkDeleteRows));
                    Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.BulkTableType));
                    Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.BulkUpdateRows));
                }

                Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.DeleteMetadata));
                Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.DeleteRow));
                Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.Reset));
                Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.SelectChanges));
                Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.SelectInitializedChanges));
                Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.SelectRow));
                Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.UpdateRow));

                // check filters are deleted
                Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.SelectChangesWithFilters));
                Assert.False(await localOrchestrator.ExistStoredProcedureAsync(clientScope, setupTable.TableName, setupTable.SchemaName, DbStoredProcedureType.SelectInitializedChangesWithFilters));
            }
        }