Example #1
0
        public void StopJobsRunningTest()
        {
            var jobTest  = new TestJob();
            var progress = new SynchronousProgress <ProgressInfo>();
            var token    = (new CancellationTokenSource()).Token;
            var jobID    = jobClient.Add(appID, () => jobTest.Start("Hello World", progress, token));

            //run job
            jobServer.RunJobs(new List <string> {
                jobID
            });
            Thread.Sleep(1000);

            var job = jobClient.GetJob(jobID);

            Assert.IsNotNull(job);
            Assert.AreEqual(JobStatus.Running, job.Status);

            jobClient.SetCommandStop(new List <string> {
                jobID
            });
            jobServer.StopJobs(); //stop running job
            Thread.Sleep(3000);

            job = jobClient.GetJob(jobID);
            Assert.AreEqual(JobStatus.Stopped, job.Status);

            jobClient.DeleteJobs(new List <string>()
            {
                jobID
            });
        }
        public async Task Combined_IncrementalProgressUpdates()
        {
            var discovery  = PartDiscovery.Combine(TestUtilities.V2Discovery, TestUtilities.V1Discovery);
            var assemblies = new[]
            {
                typeof(AssemblyDiscoveryTests.DiscoverablePart1).GetTypeInfo().Assembly,
                this.GetType().GetTypeInfo().Assembly,
            };
            DiscoveryProgress lastReceivedUpdate = default(DiscoveryProgress);
            int progressUpdateCount = 0;
            var progress            = new SynchronousProgress <DiscoveryProgress>(update =>
            {
                progressUpdateCount++;
                Assert.NotNull(update.Status);
                ////Assert.True(update.Completion >= lastReceivedUpdate.Completion); // work can be discovered that regresses this legitimately
                Assert.True(update.Completion <= 1);
                Assert.True(update.Status != lastReceivedUpdate.Status || update.Completion != lastReceivedUpdate.Completion);
                this.output.WriteLine(
                    "Completion reported: {0} ({1}/{2}): {3}",
                    update.Completion,
                    update.CompletedSteps,
                    update.TotalSteps,
                    update.Status);
                lastReceivedUpdate = update;
            });
            await discovery.CreatePartsAsync(assemblies, progress);

            progress.RethrowAnyExceptions();
            Assert.True(lastReceivedUpdate.Completion > 0);
            Assert.True(progressUpdateCount > 2);
        }
Example #3
0
        private static async Task SynchronizeAsync()
        {
            // Database script used for this sample : https://github.com/Mimetis/Dotmim.Sync/blob/master/CreateAdventureWorks.sql

            // Create a web proxy Orchesrtrator with a custom serializer
            var serverProxyOrchestrator = new WebRemoteOrchestrator("https://localhost:44342/api/sync")
            {
                Converter         = new CustomConverter(),
                SerializerFactory = new CustomMessagePackSerializerFactory()
            };

            // Second provider is using plain old Sql Server provider, relying on triggers and tracking tables to create the sync environment
            var clientProvider = new SqlSyncProvider(clientConnectionString);

            var progress = new SynchronousProgress <ProgressArgs>(args => Console.WriteLine($"{args.Context.SyncStage}:\t{args.Message}"));


            // Creating an agent that will handle all the process
            var agent = new SyncAgent(clientProvider, serverProxyOrchestrator);


            do
            {
                // Launch the sync process
                var s1 = await agent.SynchronizeAsync(progress);

                // Write results
                Console.WriteLine(s1);
            } while (Console.ReadKey().Key != ConsoleKey.Escape);

            Console.WriteLine("End");
        }
Example #4
0
        private static async Task CreateSnapshotAsync()
        {
            // [Required]: Get a connection string to your server data source
            var connectionString = configuration.GetSection("ConnectionStrings")["SqlConnection"];

            // [Required] Tables involved in the sync process:
            var tables = new string[] { "ProductCategory", "ProductModel", "Product",
                                        "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" };

            var syncOptions = new SyncOptions
            {
                SnapshotsDirectory = Path.Combine(SyncOptions.GetDefaultUserBatchDiretory(), "Snapshots"),
                BatchSize          = 2000,
            };

            var syncSetup = new SyncSetup(tables);

            // Using the Progress pattern to handle progession during the synchronization
            var progress = new SynchronousProgress <ProgressArgs>(s => Console.WriteLine($"{s.Source}:\t{s.Message}"));

            var provider = new SqlSyncProvider(connectionString);

            var orchestrator = new RemoteOrchestrator(provider, syncOptions, syncSetup);

            var snap = await orchestrator.CreateSnapshotAsync(progress : progress);
        }
Example #5
0
        private static async Task SynchronizeAsync()
        {
            // Database script used for this sample : https://github.com/Mimetis/Dotmim.Sync/blob/master/CreateAdventureWorks.sql

            var serverOrchestrator = new WebClientOrchestrator("https://localhost.fiddler:44342/api/sync");

            // Second provider is using plain old Sql Server provider, relying on triggers and tracking tables to create the sync environment
            var clientProvider = new SqlSyncProvider(clientConnectionString);


            // Creating an agent that will handle all the process
            var agent = new SyncAgent(clientProvider, serverOrchestrator);

            do
            {
                try
                {
                    var progress = new SynchronousProgress <ProgressArgs>(args => Console.WriteLine($"{args.ProgressPercentage:p}:\t{args.Message}"));
                    // Launch the sync process
                    var s1 = await agent.SynchronizeAsync(progress);

                    // Write results
                    Console.WriteLine(s1);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            } while (Console.ReadKey().Key != ConsoleKey.Escape);

            Console.WriteLine("End");
        }
        public static async Task SynchronizeLogsAsync(WebRemoteOrchestrator serverOrchestrator, SqlSyncProvider clientProvider, SyncOptions options, bool reinitialize = false)
        {
            // Creating an agent that will handle all the process
            var agent = new SyncAgent(clientProvider, serverOrchestrator, options);

            var progress = new SynchronousProgress <ProgressArgs>(
                pa => Console.WriteLine($"{pa.ProgressPercentage:p}\t {pa.Message}"));

            var syncType = reinitialize ? SyncType.Reinitialize : SyncType.Normal;

            try
            {
                // Launch the sync process
                var s1 = await agent.SynchronizeAsync("logs", syncType, progress);

                // Write results
                Console.WriteLine(s1);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.WriteLine("End");
        }
        public static async Task SynchronizeDefaultAsync(WebRemoteOrchestrator serverOrchestrator, SqlSyncProvider clientProvider, SyncOptions options, bool reinitialize = false)
        {
            var agent      = new SyncAgent(clientProvider, serverOrchestrator, options);
            var parameters = new SyncParameters
            {
                { "City", "Toronto" },
                { "postal", DBNull.Value }
            };
            var syncType = reinitialize ? SyncType.Reinitialize : SyncType.Normal;

            var progress = new SynchronousProgress <ProgressArgs>(
                pa => Console.WriteLine($"{pa.ProgressPercentage:p}\t {pa.Message}"));

            try
            {
                // Launch the sync process
                var s1 = await agent.SynchronizeAsync(syncType, progress);

                // Write results
                Console.WriteLine(s1);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
Example #8
0
        private static async Task SynchronizeAsync()
        {
            // Database script used for this sample : https://github.com/Mimetis/Dotmim.Sync/blob/master/CreateAdventureWorks.sql

            var serverOrchestrator = new WebClientOrchestrator("https://localhost.fiddler:44342/api/sync");

            var clientProvider = new SqlSyncProvider(clientConnectionString);

            var clientOptions = new SyncOptions {
                BatchSize = 500
            };

            var progress = new SynchronousProgress <ProgressArgs>(pa => Console.WriteLine($"{pa.Context.SessionId} - {pa.Context.SyncStage}\t {pa.Message}"));
            var agent    = new SyncAgent(clientProvider, serverOrchestrator, clientOptions);

            do
            {
                // Launch the sync process
                var s1 = await agent.SynchronizeAsync(progress);

                // Write results
                Console.WriteLine(s1);
            } while (Console.ReadKey().Key != ConsoleKey.Escape);

            Console.WriteLine("End");
        }
Example #9
0
    private async static Task TestVbSetup()
    {
        var serverProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(serverDbName));
        var clientProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientDbName));

        // Create the setup used for your sync process
        var tables = new string[] { "[vbs].VBSetup", };

        //  [Optional] : database setup
        var syncSetup = new SyncSetup(tables)
        {
            // optional :
            StoredProceduresPrefix = "sync_",
            StoredProceduresSuffix = "",
            TrackingTablesPrefix   = "sync_",
            TrackingTablesSuffix   = "",
            ScopeName      = "SStGMobile_Sync",
            TriggersPrefix = "sync",
        };

        var syncAgent = new SyncAgent(clientProvider, serverProvider, syncSetup);

        // Using the IProgress<T> pattern to handle progession dring the synchronization
        // Be careful, Progress<T> is not synchronous. Use SynchronousProgress<T> instead !
        var progress = new SynchronousProgress <ProgressArgs>(s => Console.WriteLine($"{s.Context.SyncStage}:\t{s.Message}"));

        var syncContext = await syncAgent.SynchronizeAsync(progress);
    }
Example #10
0
        public async Task CleanUpTest()
        {
            //Test StopJobs with CleanUp() calls

            var jobTest  = new TestJob();
            var progress = new SynchronousProgress <ProgressInfo>();
            var token    = (new CancellationTokenSource()).Token;
            var jobID    = await jobClient.AddAsync(appID, () => jobTest.Start("Hello World", progress, token));

            //run job
            await jobServer.RunJobsAsync(new List <string> {
                jobID
            });

            Thread.Sleep(1000);

            var job = await jobClient.GetJobAsync(jobID);

            Assert.IsNotNull(job);
            Assert.AreEqual(JobStatus.Running, job.Status);

            await jobClient.SetCommandStopAsync(new List <string> {
                jobID
            });

            await jobServer.CleanUpAsync();

            Thread.Sleep(3000);

            job = await jobClient.GetJobAsync(jobID);

            Assert.AreEqual(JobStatus.Stopped, job.Status);

            await jobClient.DeleteJobsAsync(new List <string>() { jobID });
        }
Example #11
0
        public override async Task DoAsync(CancellationToken cancellationToken)
        {
            Logger.Trace($"{_repository} Downloading {Path}");
            var progress = new SynchronousProgress <ulong>();

            progress.ProgressChanged += (_, count) => _done += count;
            await _repository.DownloadTo(Path, Storage, progress, cancellationToken);
        }
        protected async Task <GenerationResult> GenerateAsync(SourceText inputSource)
        {
            var solution             = this.solution.WithDocumentText(this.inputDocumentId, inputSource);
            var inputDocument        = solution.GetDocument(this.inputDocumentId);
            var generatorDiagnostics = new List <Diagnostic>();
            var progress             = new SynchronousProgress <Diagnostic>(generatorDiagnostics.Add);
            var inputCompilation     = (CSharpCompilation)await inputDocument.Project.GetCompilationAsync();

            var inputSyntaxTree = await inputDocument.GetSyntaxTreeAsync();

            var outputSyntaxTree = await DocumentTransform.TransformAsync(inputCompilation, inputSyntaxTree, null, Assembly.Load, progress);

            var outputDocument = inputDocument.Project
                                 .AddDocument("output.cs", outputSyntaxTree.GetRoot());

            // Make sure the result compiles without errors or warnings.
            var compilation = await outputDocument.Project.GetCompilationAsync();

            var compilationDiagnostics = compilation.GetDiagnostics();

            SourceText outputDocumentText = await outputDocument.GetTextAsync();

            this.logger.WriteLine("{0}", outputDocumentText);

            // Verify all line endings are consistent (otherwise VS can bug the heck out of the user if they have the generated file open).
            string firstLineEnding = null;

            foreach (var line in outputDocumentText.Lines)
            {
                string actualNewLine = line.Text.GetSubText(TextSpan.FromBounds(line.End, line.EndIncludingLineBreak)).ToString();
                if (firstLineEnding == null)
                {
                    firstLineEnding = actualNewLine;
                }
                else if (actualNewLine != firstLineEnding && actualNewLine.Length > 0)
                {
                    string expected = EscapeLineEndingCharacters(firstLineEnding);
                    string actual   = EscapeLineEndingCharacters(actualNewLine);
                    Assert.True(false, $"Expected line ending characters '{expected}' but found '{actual}' on line {line.LineNumber + 1}.\nContent: {line}");
                }
            }

            var semanticModel = await outputDocument.GetSemanticModelAsync();

            var result = new GenerationResult(outputDocument, semanticModel, generatorDiagnostics, compilationDiagnostics);

            foreach (var diagnostic in generatorDiagnostics)
            {
                this.logger.WriteLine(diagnostic.ToString());
            }

            foreach (var diagnostic in result.CompilationDiagnostics)
            {
                this.logger.WriteLine(diagnostic.ToString());
            }

            return(result);
        }
Example #13
0
        private static void AddJob()
        {
            var job         = new TestJob();
            var progress    = new SynchronousProgress <ProgressInfo>(); //just a place holder will be replaced by progress object from the server
            var cancelToken = (new CancellationTokenSource()).Token;    //just a place holder will be replaced by Token object from the server
            var pauseToken  = (new PauseTokenSource()).Token;           //just a place holder will be replaced by Token object from the server
            var jobID       = jobClient.Add("Shift.Demo.Client", () => job.Start("Hello World!", progress, cancelToken, pauseToken));

            addedJobIDs.Add(jobID);
            Console.WriteLine();
            Console.WriteLine("==> New job added to Shift DB table");
        }
Example #14
0
        public async Task ContinueJobsPausedAsyncTest()
        {
            var jobTest     = new TestJob();
            var progress    = new SynchronousProgress <ProgressInfo>();
            var cancelToken = (new CancellationTokenSource()).Token;
            var pauseToken  = (new PauseTokenSource()).Token;
            var jobID       = await jobClient.AddAsync(AppID, () => jobTest.Start("Hello World", progress, cancelToken, pauseToken));

            //run job
            await jobServer.RunJobsAsync(new List <string> {
                jobID
            });

            Thread.Sleep(1000);

            await jobClient.SetCommandPauseAsync(new List <string> {
                jobID
            });

            await jobServer.PauseJobsAsync(); //pause running job

            Thread.Sleep(3000);

            var job = await jobClient.GetJobAsync(jobID);

            Assert.NotNull(job);
            Assert.Equal(JobStatus.Paused, job.Status);

            await jobClient.SetCommandContinueAsync(new List <string> {
                jobID
            });

            await jobServer.ContinueJobsAsync(); //continue paused job

            Thread.Sleep(3000);

            job = await jobClient.GetJobAsync(jobID);

            await jobClient.SetCommandStopAsync(new List <string> {
                jobID
            });

            await jobServer.StopJobsAsync();

            Thread.Sleep(3000);
            await jobClient.DeleteJobsAsync(new List <string>() { jobID });

            Assert.Equal(JobStatus.Running, job.Status);
        }
Example #15
0
        private static async Task SynchronizeAsync()
        {
            // Database script used for this sample : https://github.com/Mimetis/Dotmim.Sync/blob/master/CreateAdventureWorks.sql

            var serverOrchestrator = new WebRemoteOrchestrator("https://localhost:44342/api/sync");

            // Second provider is using plain old Sql Server provider, relying on triggers and tracking tables to create the sync environment
            var clientProvider = new SqlSyncProvider(clientConnectionString);

            // Set the web server Options
            var options = new SyncOptions
            {
                BatchDirectory = Path.Combine(SyncOptions.GetDefaultUserBatchDiretory(), "client")
            };

            // Creating an agent that will handle all the process
            var agent = new SyncAgent(clientProvider, serverOrchestrator, options);

            var progress = new SynchronousProgress <ProgressArgs>(
                pa => Console.WriteLine($"{pa.ProgressPercentage:p}\t {pa.Message}"));

            var parameters = new SyncParameters
            {
                { "City", "Toronto" },
                // Because I've specified that "postal" could be null,
                // I can set the value to DBNull.Value (and the get all postal code in Toronto city)
                { "postal", DBNull.Value }
            };

            do
            {
                try
                {
                    // Launch the sync process
                    var s1 = await agent.SynchronizeAsync(progress);

                    // Write results
                    Console.WriteLine(s1);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            } while (Console.ReadKey().Key != ConsoleKey.Escape);

            Console.WriteLine("End");
        }
Example #16
0
        public void test(ResolverType resolverType)
        {
            // Arrange
            var initialized = false;
            var sum         = 0;
            var completed   = false;

            var task = new TaskDefinition(
                new BasicTaskStep(
                    "Initialize",
                    () => { initialized = true; }),
                PipelineTaskStep
                .Builder <int>("Pipeline")
                .WithInput(new[] { 1, 2, 3, 4, 5, 6 })
                .WithBlock("Sum", x => sum += x)
                .WithBlock("Log", x => _output.WriteLine(x.ToString()))
                .Build(),
                new BasicTaskStep(
                    "Complete",
                    () => { completed = true; }));

            var progress           = new SynchronousProgress <TaskProgress>(x => _output.WriteLine($"{x.StepName}: {x.ProgressPercentage}%"));
            var cancellationSource = new CancellationTokenSource();

            var taskEvents = new TaskExecutionEvents(
                taskStarted: x => _output.WriteLine("Task started."),
                taskEnded: x => _output.WriteLine($"Task ended after {x.Duration.Ticks} ticks."),
                stepStarted: x => _output.WriteLine($"Step '{x.Step.Name}' started."),
                stepEnded: x => _output.WriteLine($"Step '{x.Step.Name}' ended after {x.Duration.Ticks} ticks."));

            var pipelineEvents = new PipelineExecutionEvents(
                itemStarted: x => _output.WriteLine($"Item {x.ItemNumber} of step '{x.Step.Name}' started."),
                itemEnded: x => _output.WriteLine($"Item {x.ItemNumber} of step '{x.Step.Name}' ended after {x.Duration.Ticks} ticks."),
                blockStarted: x => _output.WriteLine($"Block '{x.Block.Name}' of step '{x.Step.Name}' started processing item {x.ItemNumber}."),
                blockEnded: x => _output.WriteLine($"Block '{x.Block.Name}' of step '{x.Step.Name}' ended processing item {x.ItemNumber} after {x.Duration.Ticks} ticks."));

            // Act
            var result = task.Execute(resolverType, progress, cancellationSource, taskEvents, pipelineEvents);

            // Assert
            result.Outcome.Should().Be(TaskOutcome.Successful);
            initialized.Should().Be(true);
            sum.Should().Be(21);
            completed.Should().Be(true);
        }
Example #17
0
        private static async Task UpgradeAsync()
        {
            var serverProvider = new SqlSyncProvider(serverConnectionString);

            var remoteOrchestrator = new RemoteOrchestrator(serverProvider);

            do
            {
                var progress = new SynchronousProgress <ProgressArgs>(args => Console.WriteLine($"{args.ProgressPercentage:p}:\t{args.Message}"));

                await remoteOrchestrator.UpgradeAsync(progress : progress);

                // Write results
                Console.WriteLine("Upgrade to last version done");
            } while (Console.ReadKey().Key != ConsoleKey.Escape);

            Console.WriteLine("End");
        }
Example #18
0
        private void test(
            ResolverType resolverType,
            ITaskStep taskStep,
            ICollection <byte> expectedProgressReports)
        {
            // Arrange
            var progressReports = new List <TaskProgress>();

            var task = new TaskDefinition(taskStep);

            var progress = new SynchronousProgress <TaskProgress>(x => progressReports.Add(x));

            // Act
            task.Execute(resolverType, progress);

            // Assert
            progressReports.Select(x => x.StepName).Should().OnlyContain(x => x == taskStep.Name);
            progressReports.Select(x => x.ProgressPercentage).Should().BeEquivalentTo(expectedProgressReports);
        }
Example #19
0
        private void ExecuteStep <TStep>(
            TStep step,
            TaskDefinition task,
            IProgress <TaskProgress> progress,
            CancellationToken cancellation)
            where TStep : ITaskStep
        {
            var stepExecutor = _taskStepExecutorResolver.Resolve <TStep>();

            var context = new TaskStepExecutionContext
            {
                Task      = task,
                EventsBag = _executionEventsBag
            };

            var stepProgress = new SynchronousProgress <byte>(
                x => progress.Report(new TaskProgress
            {
                StepName           = step.Name,
                ProgressPercentage = x
            }));

            stepExecutor.Execute(step, context, stepProgress, cancellation);
        }
Example #20
0
    private static async Task SynchronizeThenDeprovisionThenProvisionAsync()
    {
        // Create 2 Sql Sync providers
        var serverProvider = new SqlSyncProvider(DBHelper.GetDatabaseConnectionString(serverDbName));
        var clientProvider = new SqlSyncProvider(DBHelper.GetDatabaseConnectionString(clientDbName));

        // Create standard Setup and Options
        var setup   = new SyncSetup(new string[] { "Address", "Customer", "CustomerAddress" });
        var options = new SyncOptions();

        // Creating an agent that will handle all the process
        var agent = new SyncAgent(clientProvider, serverProvider, options, setup);

        // Using the Progress pattern to handle progession during the synchronization
        var progress = new SynchronousProgress <ProgressArgs>(s => Console.WriteLine($"{s.Context.SyncStage}:\t{s.Message}"));

        // First sync to have a starting point
        var s1 = await agent.SynchronizeAsync(progress);

        Console.WriteLine(s1);

        // -----------------------------------------------------------------
        // Migrating a table by adding a new column
        // -----------------------------------------------------------------

        // Adding a new column called CreatedDate to Address table, on the server, and on the client.
        await AddNewColumnToAddressAsync(serverProvider.CreateConnection());
        await AddNewColumnToAddressAsync(clientProvider.CreateConnection());

        // -----------------------------------------------------------------
        // Server side
        // -----------------------------------------------------------------

        // Creating a setup regarding only the table Address
        var setupAddress = new SyncSetup(new string[] { "Address" });

        // Create a server orchestrator used to Deprovision and Provision only table Address
        var remoteOrchestrator = new RemoteOrchestrator(serverProvider, options, setupAddress);

        // Unprovision the Address triggers / stored proc.
        // We can conserve the Address tracking table, since we just add a column,
        // that is not a primary key used in the tracking table
        // That way, we are preserving historical data
        await remoteOrchestrator.DeprovisionAsync(SyncProvision.StoredProcedures | SyncProvision.Triggers);

        // Provision the Address triggers / stored proc again,
        // This provision method will fetch the address schema from the database,
        // so it will contains all the columns, including the new Address column added
        await remoteOrchestrator.ProvisionAsync(SyncProvision.StoredProcedures | SyncProvision.Triggers);

        // Now we need the full setup to get the full schema.
        // Setup includes [Address] [Customer] and [CustomerAddress]
        remoteOrchestrator.Setup = setup;
        var newSchema = await remoteOrchestrator.GetSchemaAsync();

        // Now we need to save this new schema to the serverscope table
        // get the server scope again
        var serverScope = await remoteOrchestrator.GetServerScopeAsync();

        // affect good values
        serverScope.Setup  = setup;
        serverScope.Schema = newSchema;

        // save it
        await remoteOrchestrator.WriteServerScopeAsync(serverScope);

        // -----------------------------------------------------------------
        // Client side
        // -----------------------------------------------------------------

        // Now go for local orchestrator
        var localOrchestrator = new LocalOrchestrator(clientProvider, options, setupAddress);

        // Unprovision the Address triggers / stored proc. We can conserve tracking table, since we just add a column, that is not a primary key used in the tracking table
        // In this case, we will
        await localOrchestrator.DeprovisionAsync(SyncProvision.StoredProcedures | SyncProvision.Triggers);

        // Provision the Address triggers / stored proc again,
        // This provision method will fetch the address schema from the database, so it will contains all the columns, including the new one added
        await localOrchestrator.ProvisionAsync(SyncProvision.StoredProcedures | SyncProvision.Triggers);

        // Now we need to save this to clientscope
        // get the server scope again
        var clientScope = await localOrchestrator.GetClientScopeAsync();

        // At this point, if you need the schema and you are not able to create a RemoteOrchestrator,
        // You can create a WebClientOrchestrator and get the schema as well
        // var proxyClientProvider = new WebClientOrchestrator("https://localhost:44369/api/Sync");
        // var newSchema = proxyClientProvider.GetSchemaAsync();

        // affect good values
        clientScope.Setup  = setup;
        clientScope.Schema = newSchema;

        // save it
        await localOrchestrator.WriteClientScopeAsync(clientScope);



        // Now test a new sync, everything should work as expected.
        do
        {
            // Console.Clear();
            Console.WriteLine("Sync Start");
            try
            {
                var s2 = await agent.SynchronizeAsync();

                // Write results
                Console.WriteLine(s2);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        } while (Console.ReadKey().Key != ConsoleKey.Escape);

        Console.WriteLine("End");
    }
Example #21
0
    private static async Task TestDeleteWithoutBulkAsync()
    {
        var cs = DBHelper.GetDatabaseConnectionString(serverProductCategoryDbName);
        var cc = DBHelper.GetDatabaseConnectionString(clientDbName);

        // Create 2 Sql Sync providers
        var serverProvider   = new SqlSyncProvider(cs);
        var serverConnection = new SqlConnection(cs);

        //var clientProvider = new SqlSyncProvider(cc);
        //var clientConnection = new SqlConnection(cc);

        var clientProvider   = new SqliteSyncProvider("advworks2.db");
        var clientConnection = new SqliteConnection(clientProvider.ConnectionString);

        // Creating an agent that will handle all the process
        var agent = new SyncAgent(clientProvider, serverProvider, new string[] { "ProductCategory" });

        // Using the Progress pattern to handle progession during the synchronization
        var progress = new SynchronousProgress <ProgressArgs>(s =>
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine($"{s.Context.SyncStage}:\t{s.Message}");
            Console.ResetColor();
        });

        var remoteProgress = new SynchronousProgress <ProgressArgs>(s =>
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine($"{s.Context.SyncStage}:\t{s.Message}");
            Console.ResetColor();
        });

        // agent.AddRemoteProgress(remoteProgress);

        agent.Options.BatchDirectory    = Path.Combine(SyncOptions.GetDefaultUserBatchDiretory(), "sync");
        agent.Options.BatchSize         = 0;
        agent.Options.UseBulkOperations = false;
        agent.Options.DisableConstraintsOnApplyChanges = false;
        agent.Options.ConflictResolutionPolicy         = ConflictResolutionPolicy.ClientWins;

        Console.WriteLine("Sync Start");
        var s1 = await agent.SynchronizeAsync(progress);

        Console.WriteLine(s1);

        Console.WriteLine("Insert product category on Server");
        var id = InsertOneProductCategoryId(serverConnection, "GLASSES");

        Console.WriteLine("Update Done.");

        Console.WriteLine("Update product category on Server");
        UpdateOneProductCategoryId(serverConnection, id, "OVERGLASSES");
        Console.WriteLine("Update Done.");

        Console.WriteLine("Sync Start");
        s1 = await agent.SynchronizeAsync(progress);

        Console.WriteLine(s1);

        Console.WriteLine("End");
    }
Example #22
0
    /// <summary>
    /// Test a client syncing through a web api
    /// </summary>
    private static async Task SyncThroughWebApiAsync()
    {
        var clientProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientDbName));

        var handler = new HttpClientHandler {
            AutomaticDecompression = DecompressionMethods.GZip
        };
        var client = new HttpClient(handler)
        {
            Timeout = TimeSpan.FromMinutes(5)
        };

        var proxyClientProvider = new WebClientOrchestrator("http://localhost:52288/api/Sync", null, null, client);



        // ----------------------------------
        // Client side
        // ----------------------------------
        var clientOptions = new SyncOptions
        {
            ScopeInfoTableName = "client_scopeinfo",
            BatchDirectory     = Path.Combine(SyncOptions.GetDefaultUserBatchDiretory(), "sync_client"),
            BatchSize          = 50,
            CleanMetadatas     = true,
            UseBulkOperations  = true,
            UseVerboseErrors   = false,
        };

        var clientSetup = new SyncSetup
        {
            StoredProceduresPrefix = "cli",
            StoredProceduresSuffix = "",
            TrackingTablesPrefix   = "cli",
            TrackingTablesSuffix   = "",
            TriggersPrefix         = "",
            TriggersSuffix         = "",
        };


        var agent = new SyncAgent(clientProvider, proxyClientProvider, clientSetup, clientOptions);

        Console.WriteLine("Press a key to start (be sure web api is running ...)");
        Console.ReadKey();
        do
        {
            Console.Clear();
            Console.WriteLine("Web sync start");
            try
            {
                var progress = new SynchronousProgress <ProgressArgs>(pa => Console.WriteLine($"{pa.Context.SessionId} - {pa.Context.SyncStage}\t {pa.Message}"));

                var s = await agent.SynchronizeAsync(progress);

                Console.WriteLine(s);
            }
            catch (SyncException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("UNKNOW EXCEPTION : " + e.Message);
            }


            Console.WriteLine("Sync Ended. Press a key to start again, or Escapte to end");
        } while (Console.ReadKey().Key != ConsoleKey.Escape);

        Console.WriteLine("End");
    }
Example #23
0
        private static async Task SynchronizeAsync(CoreProvider clientProvider)
        {
            // Database script used for this sample : https://github.com/Mimetis/Dotmim.Sync/blob/master/CreateAdventureWorks.sql

            var serverOrchestrator = new WebClientOrchestrator("https://localhost:44342/api/sync");


            // Creating an agent that will handle all the process
            var agent = new SyncAgent(clientProvider, serverOrchestrator);

            try
            {
                var progress = new SynchronousProgress <ProgressArgs>(args => Console.WriteLine($"{args.PogressPercentageString}:\t{args.Message}"));

                // Get the client scope
                var scope = await agent.LocalOrchestrator.GetClientScopeAsync();

                if (scope.IsNewScope)
                {
                    var client           = new HttpClient();
                    var seedingsResponse = await client.GetAsync($"https://localhost:44342/api/sync/seedings/{scope.Id}");

                    seedingsResponse.EnsureSuccessStatusCode();

                    var seedingsResponseString = await seedingsResponse.Content.ReadAsStringAsync();

                    var seedings = JsonConvert.DeserializeObject <List <Seeding> >(seedingsResponseString);

                    agent.LocalOrchestrator.OnTableCreating(async tca =>
                    {
                        var tableName  = tca.TableName.Unquoted().ToString();
                        var schemaName = string.IsNullOrEmpty(tca.TableName.SchemaName) ? "dbo" : tca.TableName.SchemaName;

                        var seeding = seedings.FirstOrDefault(s => s.TableName == tableName && s.SchemaName == schemaName);
                        var id      = tca.Table.GetPrimaryKeysColumns().ToList()[0];

                        if (seeding != null && id.IsAutoIncrement)
                        {
                            id.AutoIncrementSeed = seeding.Seed;
                            id.AutoIncrementStep = seeding.Step;
                        }

                        var newTableBuilder = agent.LocalOrchestrator.GetTableBuilder(tca.Table, agent.LocalOrchestrator.Setup);

                        var newCommand = await newTableBuilder.GetCreateTableCommandAsync(tca.Connection, tca.Transaction);

                        tca.Command.CommandText = newCommand.CommandText;
                    });
                }

                // Launch the sync process
                var s1 = await agent.SynchronizeAsync(progress);

                // Write results
                Console.WriteLine(s1);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.WriteLine("End");
        }
Example #24
0
        private static async Task SynchronizeAsync()
        {
            // Database script used for this sample : https://github.com/Mimetis/Dotmim.Sync/blob/master/CreateAdventureWorks.sql

            // Create 2 Sql Sync providers
            // First provider is using the Sql change tracking feature. Don't forget to enable it on your database until running this code !
            // For instance, use this SQL statement on your server database : ALTER DATABASE AdventureWorks  SET CHANGE_TRACKING = ON  (CHANGE_RETENTION = 10 DAYS, AUTO_CLEANUP = ON)
            // Otherwise, if you don't want to use Change Tracking feature, just change 'SqlSyncChangeTrackingProvider' to 'SqlSyncProvider'
            var serverProvider = new SqlSyncChangeTrackingProvider(serverConnectionString);
            var clientProvider = new SqlSyncProvider(clientConnectionString);

            // Tables involved in the sync process:
            var tables = new string[] { "ProductCategory", "ProductModel", "Product",
                                        "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" };

            // Creating an agent that will handle all the process
            var agent = new SyncAgent(clientProvider, serverProvider, tables);

            agent.Options.BatchSize = 20;

            // Using the IProgress<T> pattern to handle progession dring the synchronization
            // Be careful, Progress<T> is not synchronous. Use SynchronousProgress<T> instead !
            var progress = new SynchronousProgress <ProgressArgs>(args => Console.WriteLine($"{args.PogressPercentageString}:\t{args.Message}"));

            // --------------------------------------------
            // Using Interceptors
            // --------------------------------------------

            // CancellationTokenSource is used to cancel a sync process in the next example
            var cts = new CancellationTokenSource();

            // Intercept a table changes selecting
            // Because the changes are not yet selected, we can easily interrupt the process with the cancellation token
            agent.LocalOrchestrator.OnTableChangesSelecting(args =>
            {
                Console.WriteLine($"-------- Getting changes from table {args.Table.GetFullName()} ...");

                if (args.Table.TableName == "Table_That_Should_Not_Be_Sync")
                {
                    cts.Cancel();
                }
            });

            // Intercept a table changes applying with a particular state [Upsert] or [Deleted]
            // The rows included in the args.Changes table will be applied right after.
            agent.LocalOrchestrator.OnTableChangesBatchApplying(args =>
            {
                Console.WriteLine($"-------- Applying changes {args.State} to table {args.Changes.GetFullName()} ...");

                if (args.Changes == null || args.Changes.Rows.Count == 0)
                {
                    return;
                }

                foreach (var row in args.Changes.Rows)
                {
                    Console.WriteLine(row);
                }
            });

            // Intercept a table changes selected.
            // The rows included in the args.Changes have been selected from the datasource and will be sent to the server
            agent.LocalOrchestrator.OnTableChangesSelected(args =>
            {
                if (args.Changes == null || args.Changes.Rows.Count == 0)
                {
                    return;
                }

                foreach (var row in args.Changes.Rows)
                {
                    Console.WriteLine(row);
                }
            });

            // ------------------------
            // Because we are in a TCP mode, we can hook the server side events
            // In an HTTP mode, the code below won't work
            // ------------------------

            agent.RemoteOrchestrator.OnTableChangesSelecting(args =>
            {
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine($"-------- Getting changes from table {args.Table.GetFullName()} ...");
                Console.ResetColor();
            });

            agent.RemoteOrchestrator.OnTableChangesSelected(args =>
            {
                if (args.Changes == null || args.Changes.Rows.Count == 0)
                {
                    return;
                }

                Console.ForegroundColor = ConsoleColor.Yellow;
                foreach (var row in args.Changes.Rows)
                {
                    Console.WriteLine(row);
                }
                Console.ResetColor();
            });

            agent.RemoteOrchestrator.OnTableChangesBatchApplying(args =>
            {
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine($"-------- Applying changes {args.State} to table {args.Changes.GetFullName()} ...");

                if (args.Changes == null || args.Changes.Rows.Count == 0)
                {
                    return;
                }

                foreach (var row in args.Changes.Rows)
                {
                    Console.WriteLine(row);
                }
                Console.ResetColor();
            });
            do
            {
                // Launch the sync process
                var s1 = await agent.SynchronizeAsync(SyncType.Normal, cts.Token, progress);

                // Write results
                Console.WriteLine(s1);
            } while (Console.ReadKey().Key != ConsoleKey.Escape);

            Console.WriteLine("End");
        }
Example #25
0
    private static async Task CreateSnapshotAsync()
    {
        // Create 2 Sql Sync providers
        var serverProvider     = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(serverDbName));
        var remoteOrchestrator = new RemoteOrchestrator(serverProvider);

        // specific Setup with only 2 tables, and one filtered
        var setup = new SyncSetup(allTables);

        // snapshot directory
        var directory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Snapshots");


        await remoteOrchestrator.CreateSnapshotAsync(new SyncContext(), setup, directory, 500, CancellationToken.None);

        // client provider
        var clientProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientDbName));

        // Insert a value after snapshot created
        using (var c = serverProvider.CreateConnection())
        {
            var command = c.CreateCommand();
            command.CommandText = "INSERT INTO [dbo].[ProductCategory] ([Name]) VALUES ('Bikes revolution');";
            c.Open();
            command.ExecuteNonQuery();
            c.Close();
        }

        // Creating an agent that will handle all the process
        var agent = new SyncAgent(clientProvider, serverProvider, setup);

        var syncOptions = new SyncOptions {
            SnapshotsDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Snapshots")
        };

        // Setting the snapshots directory for client
        agent.Options.SnapshotsDirectory = directory;

        // Using the Progress pattern to handle progession during the synchronization
        var progress = new SynchronousProgress <ProgressArgs>(s =>
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine($"{s.Context.SyncStage}:\t{s.Message}");
            Console.ResetColor();
        });

        var remoteProgress = new SynchronousProgress <ProgressArgs>(s =>
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($"{s.Context.SyncStage}:\t{s.Message}");
            Console.ResetColor();
        });


        //// Launch the sync process
        //if (!agent.Parameters.Contains("City"))
        //    agent.Parameters.Add("City", "Toronto");

        //if (!agent.Parameters.Contains("postal"))
        //    agent.Parameters.Add("postal", "NULL");



        do
        {
            Console.Clear();
            Console.WriteLine("Sync Start");
            try
            {
                var s1 = await agent.SynchronizeAsync(progress);

                Console.WriteLine(s1);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        } while (Console.ReadKey().Key != ConsoleKey.Escape);

        Console.WriteLine("End");
    }
Example #26
0
    private static async Task SynchronizeMultiScopesAsync()
    {
        // Create 2 Sql Sync providers
        var serverProvider = new SqlSyncChangeTrackingProvider(DbHelper.GetDatabaseConnectionString(serverDbName));
        var clientProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientDbName));

        // Create 2 tables list (one for each scope)
        string[] productScopeTables   = new string[] { "ProductCategory", "ProductModel", "Product" };
        string[] customersScopeTables = new string[] { "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" };

        // Create 2 sync setup with named scope
        var setupProducts  = new SyncSetup(productScopeTables, "productScope");
        var setupCustomers = new SyncSetup(customersScopeTables, "customerScope");

        // Create 2 agents, one for each scope
        var agentProducts  = new SyncAgent(clientProvider, serverProvider, setupProducts);
        var agentCustomers = new SyncAgent(clientProvider, serverProvider, setupCustomers);

        // Using the Progress pattern to handle progession during the synchronization
        // We can use the same progress for each agent
        var progress = new SynchronousProgress <ProgressArgs>(s =>
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine($"{s.Context.SyncStage}:\t{s.Message}");
            Console.ResetColor();
        });

        var remoteProgress = new SynchronousProgress <ProgressArgs>(s =>
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($"{s.Context.SyncStage}:\t{s.Message}");
            Console.ResetColor();
        });

        // Spying what's going on the server side
        agentProducts.AddRemoteProgress(remoteProgress);
        agentCustomers.AddRemoteProgress(remoteProgress);


        do
        {
            Console.Clear();
            Console.WriteLine("Sync Start");
            try
            {
                Console.WriteLine("Hit 1 for sync Products. Hit 2 for sync customers and sales");
                var k = Console.ReadKey().Key;

                if (k == ConsoleKey.D1)
                {
                    Console.WriteLine("Sync Products:");
                    var s1 = await agentProducts.SynchronizeAsync(progress);

                    Console.WriteLine(s1);
                }
                else
                {
                    Console.WriteLine("Sync Customers and Sales:");
                    var s1 = await agentCustomers.SynchronizeAsync(progress);

                    Console.WriteLine(s1);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        } while (Console.ReadKey().Key != ConsoleKey.Escape);

        Console.WriteLine("End");
    }
Example #27
0
    /// <summary>
    /// Launch a simple sync, over TCP network, each sql server (client and server are reachable through TCP cp
    /// </summary>
    /// <returns></returns>
    private static async Task SynchronizeAsync()
    {
        // Create 2 Sql Sync providers
        var serverProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(serverDbName));
        //var clientProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientDbName));
        var clientProvider = new SqliteSyncProvider("clientX.db");

        //var setup = new SyncSetup(new string[] { "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" });
        var setup = new SyncSetup(allTables);

        setup.Filters.Add("Customer", "CompanyName");

        var addressCustomerFilter = new SetupFilter("CustomerAddress");

        addressCustomerFilter.AddParameter("CompanyName", "Customer");
        addressCustomerFilter.AddJoin(Join.Left, "Customer").On("CustomerAddress", "CustomerId", "Customer", "CustomerId");
        addressCustomerFilter.AddWhere("CompanyName", "Customer", "CompanyName");
        setup.Filters.Add(addressCustomerFilter);

        var addressFilter = new SetupFilter("Address");

        addressFilter.AddParameter("CompanyName", "Customer");
        addressFilter.AddJoin(Join.Left, "CustomerAddress").On("CustomerAddress", "AddressId", "Address", "AddressId");
        addressFilter.AddJoin(Join.Left, "Customer").On("CustomerAddress", "CustomerId", "Customer", "CustomerId");
        addressFilter.AddWhere("CompanyName", "Customer", "CompanyName");
        setup.Filters.Add(addressFilter);

        var orderHeaderFilter = new SetupFilter("SalesOrderHeader");

        orderHeaderFilter.AddParameter("CompanyName", "Customer");
        orderHeaderFilter.AddJoin(Join.Left, "CustomerAddress").On("CustomerAddress", "CustomerId", "SalesOrderHeader", "CustomerId");
        orderHeaderFilter.AddJoin(Join.Left, "Customer").On("CustomerAddress", "CustomerId", "Customer", "CustomerId");
        orderHeaderFilter.AddWhere("CompanyName", "Customer", "CompanyName");
        setup.Filters.Add(orderHeaderFilter);

        var orderDetailsFilter = new SetupFilter("SalesOrderDetail");

        orderDetailsFilter.AddParameter("CompanyName", "Customer");
        orderDetailsFilter.AddJoin(Join.Left, "SalesOrderHeader").On("SalesOrderDetail", "SalesOrderID", "SalesOrderHeader", "SalesOrderID");
        orderDetailsFilter.AddJoin(Join.Left, "CustomerAddress").On("CustomerAddress", "CustomerId", "SalesOrderHeader", "CustomerId");
        orderDetailsFilter.AddJoin(Join.Left, "Customer").On("CustomerAddress", "CustomerId", "Customer", "CustomerId");
        orderDetailsFilter.AddWhere("CompanyName", "Customer", "CompanyName");
        setup.Filters.Add(orderDetailsFilter);


        // Add pref suf
        setup.StoredProceduresPrefix = "s";
        setup.StoredProceduresSuffix = "";
        setup.TrackingTablesPrefix   = "t";
        setup.TrackingTablesSuffix   = "";

        // Creating an agent that will handle all the process
        var agent = new SyncAgent(clientProvider, serverProvider, setup);

        // Using the Progress pattern to handle progession during the synchronization
        var progress = new SynchronousProgress <ProgressArgs>(s =>
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine($"{s.Context.SyncStage}:\t{s.Message}");
            Console.ResetColor();
        });

        var remoteProgress = new SynchronousProgress <ProgressArgs>(s =>
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($"{s.Context.SyncStage}:\t{s.Message}");
            Console.ResetColor();
        });

        agent.AddRemoteProgress(remoteProgress);

        //agent.Options.BatchDirectory = Path.Combine(SyncOptions.GetDefaultUserBatchDiretory(), "sync");
        agent.Options.BatchSize         = 1000;
        agent.Options.CleanMetadatas    = true;
        agent.Options.UseBulkOperations = false;
        agent.Options.DisableConstraintsOnApplyChanges = false;
        agent.Options.ConflictResolutionPolicy         = ConflictResolutionPolicy.ClientWins;
        //agent.Options.UseVerboseErrors = false;
        //agent.Options.ScopeInfoTableName = "tscopeinfo";

        var myRijndael = new RijndaelManaged();

        myRijndael.GenerateKey();
        myRijndael.GenerateIV();

        //agent.RemoteOrchestrator.OnSerializingSet(ssa =>
        //{
        //    // Create an encryptor to perform the stream transform.
        //    var encryptor = myRijndael.CreateEncryptor(myRijndael.Key, myRijndael.IV);

        //    using (var msEncrypt = new MemoryStream())
        //    {
        //        using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
        //        {
        //            using (var swEncrypt = new StreamWriter(csEncrypt))
        //            {
        //                //Write all data to the stream.
        //                var strSet = JsonConvert.SerializeObject(ssa.Set);
        //                swEncrypt.Write(strSet);
        //            }
        //            ssa.Data = msEncrypt.ToArray();
        //        }
        //    }
        //});

        //agent.OnApplyChangesFailed(acf =>
        //{
        //    // Check conflict is correctly set
        //    var localRow = acf.Conflict.LocalRow;
        //    var remoteRow = acf.Conflict.RemoteRow;

        //    // Merge row
        //    acf.Resolution = ConflictResolution.MergeRow;

        //    acf.FinalRow["Name"] = "Prout";

        //});

        do
        {
            Console.Clear();
            Console.WriteLine("Sync Start");
            try
            {
                // Launch the sync process
                if (!agent.Parameters.Contains("CompanyName"))
                {
                    agent.Parameters.Add("CompanyName", "Professional Sales and Service");
                }

                //if (!agent.Parameters.Contains("postal"))
                //    agent.Parameters.Add("postal", DBNull.Value);


                var s1 = await agent.SynchronizeAsync(progress);

                // Write results
                Console.WriteLine(s1);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }


            //Console.WriteLine("Sync Ended. Press a key to start again, or Escapte to end");
        } while (Console.ReadKey().Key != ConsoleKey.Escape);

        Console.WriteLine("End");
    }
Example #28
0
        private static async Task SynchronizeThenDeprovisionThenProvisionAsync()
        {
            // Create 2 Sql Sync providers
            var serverProvider = new SqlSyncProvider(serverConnectionString);
            var clientProvider = new SqlSyncProvider(clientConnectionString);

            // Create standard Setup and Options
            var setup   = new SyncSetup(new string[] { "Address", "Customer", "CustomerAddress" });
            var options = new SyncOptions();

            // Creating an agent that will handle all the process
            var agent = new SyncAgent(clientProvider, serverProvider, options, setup);

            // Using the Progress pattern to handle progession during the synchronization
            var progress = new SynchronousProgress <ProgressArgs>(args => Console.WriteLine($"{args.ProgressPercentage:p}:\t{args.Message}"));

            // First sync to have a starting point
            var s1 = await agent.SynchronizeAsync(progress);

            Console.WriteLine(s1);

            // -----------------------------------------------------------------
            // Migrating a table by adding a new column
            // -----------------------------------------------------------------

            // Adding a new column called CreatedDate to Address table, on the server, and on the client.
            await Helper.AddNewColumnToAddressAsync(serverProvider.CreateConnection());

            await Helper.AddNewColumnToAddressAsync(clientProvider.CreateConnection());

            // -----------------------------------------------------------------
            // Server side
            // -----------------------------------------------------------------

            // Creating a setup regarding only the table Address
            var setupAddress = new SyncSetup(new string[] { "Address" });

            // Create a server orchestrator used to Deprovision and Provision only table Address
            var remoteOrchestrator = new RemoteOrchestrator(serverProvider, options, setupAddress);

            // Unprovision the old Address triggers / stored proc.
            // We can conserve the Address tracking table, since we just add a column,
            // that is not a primary key used in the tracking table
            // That way, we are preserving historical data
            await remoteOrchestrator.DeprovisionAsync(SyncProvision.StoredProcedures | SyncProvision.Triggers);

            // Provision the new Address triggers / stored proc again,
            // This provision method will fetch the address schema from the database,
            // so it will contains all the columns, including the new Address column added
            await remoteOrchestrator.ProvisionAsync(SyncProvision.StoredProcedures | SyncProvision.Triggers);

            // -----------------------------------------------------------------
            // Client side
            // -----------------------------------------------------------------

            // Now go for local orchestrator
            var localOrchestrator = new LocalOrchestrator(clientProvider, options, setupAddress);

            // Unprovision the Address triggers / stored proc. We can conserve tracking table, since we just add a column, that is not a primary key used in the tracking table
            // In this case, we will
            await localOrchestrator.DeprovisionAsync(SyncProvision.StoredProcedures | SyncProvision.Triggers);

            // Provision the Address triggers / stored proc again,
            // This provision method will fetch the address schema from the database, so it will contains all the columns, including the new one added
            await localOrchestrator.ProvisionAsync(SyncProvision.StoredProcedures | SyncProvision.Triggers);

            // Now test a new sync, everything should work as expected.
            do
            {
                // Console.Clear();
                Console.WriteLine("Sync Start");
                try
                {
                    var s2 = await agent.SynchronizeAsync();

                    // Write results
                    Console.WriteLine(s2);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            } while (Console.ReadKey().Key != ConsoleKey.Escape);

            Console.WriteLine("End");
        }
Example #29
0
        private static async Task MigrateClientsUsingMultiScopesAsync()
        {
            // Create the server Sync provider
            var serverProvider = new SqlSyncProvider(serverConnectionString);

            // Create 2 clients. First will migrate, 2nd will stay without new column
            var client1Provider = new SqlSyncProvider(clientConnectionString);
            var databaseName    = $"{Path.GetRandomFileName().Replace(".", "").ToLowerInvariant()}.db";
            var client2Provider = new SqliteSyncProvider(databaseName);

            // Create standard Setup
            var setup = new SyncSetup("Address", "Customer", "CustomerAddress");

            // Creating agents that will handle all the process
            var agent1 = new SyncAgent(client1Provider, serverProvider);
            var agent2 = new SyncAgent(client2Provider, serverProvider);

            // Using the Progress pattern to handle progession during the synchronization
            var progress = new SynchronousProgress <ProgressArgs>(args => Console.WriteLine($"{args.ProgressPercentage:p}:\t{args.Message}"));

            // First sync to have a starting point
            // To make a full example, we are going to use differente scope name (v0, v1)
            // v0 is the initial database
            // v1 will contains the new column in the Address table
            var s1 = await agent1.SynchronizeAsync("v0", setup, progress);

            Console.WriteLine("Initial Sync on Sql Server Client 1");
            Console.WriteLine(s1);

            var s2 = await agent2.SynchronizeAsync("v0", setup, progress);

            Console.WriteLine("Initial Sync on Sqlite Client 2");
            Console.WriteLine(s2);


            // -----------------------------------------------------------------
            // Migrating a table by adding a new column
            // -----------------------------------------------------------------

            // Adding a new column called CreatedDate to Address table, on the server
            await Helper.AddNewColumnToAddressAsync(new SqlConnection(serverConnectionString));

            Console.WriteLine("Column added on server");

            // -----------------------------------------------------------------
            // Server side
            // -----------------------------------------------------------------

            // Creating a new setup with the same tables
            // We are going to provision a new scope (v1)
            // Since this scope is not existing yet, it will force DMS to refresh the schema and
            // get the new column
            var setupAddress = new SyncSetup("Address", "Customer", "CustomerAddress");

            // Create a server orchestrator used to Deprovision and Provision only table Address
            var remoteOrchestrator = new RemoteOrchestrator(serverProvider);

            // Provision everything again for this new scope v1,
            // This provision method will fetch the address schema from the database,
            // since the new scope name is not existing yet
            // so it will contains all the columns, including the new Address column added
            await remoteOrchestrator.ProvisionAsync("v1", setupAddress, progress : progress);

            Console.WriteLine("Server migration with new column CreatedDate done.");


            // At this point, server database has two scopes:
            // v0   : first scope with Address table without the new column
            // v1   : second scope with Address table with the new column CreatedDate

            // Take a look at the database in SQL management studio and see differences in stored proc

            // Now add a row on the server (with the new column)
            var addressId = await Helper.InsertOneAddressWithNewColumnAsync(new SqlConnection(serverConnectionString));

            Console.WriteLine($"New address row added with pk {addressId}");

            // -----------------------------------------------------------------
            // SQlite Client will stay on old schema (without the new CreatedDate column)
            // -----------------------------------------------------------------

            // First of all, we are still able to sync the local database without having to migrate the client
            // allows old clients that do not have the new column, to continue sync normally
            // these old clients will continue to sync on the v0 scope

            var s3 = await agent2.SynchronizeAsync("v0", setup, progress : progress);

            Console.WriteLine($"Sqlite not migrated, doing a sync on first scope v0:");
            Console.WriteLine(s3);

            // If we get the row from the client, we have the new row inserted on server,
            // but without the new column
            var client2row = await Helper.GetLastAddressRowAsync(client2Provider.CreateConnection(), addressId);

            Console.WriteLine(client2row);

            // -----------------------------------------------------------------
            // SQL Server Client will add the column and will sync on the new scope (with the new CreatedDate column)
            // -----------------------------------------------------------------

            // Now we are going to upgrade the client 1

            // adding the column to the client
            await Helper.AddNewColumnToAddressAsync(new SqlConnection(clientConnectionString));

            Console.WriteLine("Sql Server client1 migration with new column CreatedDate done.");

            // Provision client with the new the V1 scope
            // Getting the scope from server and apply it locally
            var serverScope = await agent1.RemoteOrchestrator.GetServerScopeInfoAsync("v1", progress : progress);

            var v1clientScope = await agent1.LocalOrchestrator.ProvisionAsync(serverScope, progress : progress);

            Console.WriteLine("Sql Server client1 Provision done.");

            // if you look the stored procs on your local sql database
            // you will that you have the two scopes (v0 and v1)

            // TRICKY PART

            /*
             *  The scope v1 is new.
             *  If we sync now, since v1 is new, we are going to sync all the rows from start
             *  What we want is to sync from the last point we sync the old v0 scope
             *  That's why we are shadowing the metadata info from v0 into v1
             */
            var v0clientScope = await agent1.LocalOrchestrator.GetClientScopeInfoAsync("v0");

            v1clientScope.ShadowScope(v0clientScope);
            v1clientScope = await agent1.LocalOrchestrator.SaveClientScopeInfoAsync(v1clientScope);

            // Now test a new sync, on this new scope v1
            var s4 = await agent1.SynchronizeAsync("v1", progress : progress);

            Console.WriteLine($"Sql Server client1 migrated, doing a sync on second scope v1:");
            Console.WriteLine(s4);

            // If we get the client row from the client database, it should contains the value
            var client1row = await Helper.GetLastAddressRowAsync(new SqlConnection(clientConnectionString), addressId);

            Console.WriteLine(client1row);

            // OPTIONAL
            // -----------------------------------------------------------------

            // On this new client, migrated, we no longer need the v0 scope
            // we can deprovision it
            await agent1.LocalOrchestrator.DeprovisionAsync("v0", SyncProvision.StoredProcedures, progress : progress);

            await agent1.LocalOrchestrator.DeleteClientScopeInfoAsync(v0clientScope, progress : progress);

            Console.WriteLine($"Deprovision of old scope v0 done on Sql Server client1");

            // -----------------------------------------------------------------
            // SQLite Client will eventually migrate to v1
            // -----------------------------------------------------------------

            // It's time to migrate the sqlite client
            // Adding the column to the SQLite client
            await Helper.AddNewColumnToAddressAsync(client2Provider.CreateConnection());

            Console.WriteLine($"Column eventually added to Sqlite client2");

            // Provision SQLite client with the new the V1 scope
            var v1client2Scope = await agent2.LocalOrchestrator.ProvisionAsync(serverScope, progress : progress);

            Console.WriteLine($"Provision v1 done on SQLite client2");

            // ShadowScope old scope to new scope
            var v0client2Scope = await agent2.LocalOrchestrator.GetClientScopeInfoAsync("v0");

            v1client2Scope.ShadowScope(v0client2Scope);
            v1client2Scope = await agent2.LocalOrchestrator.SaveClientScopeInfoAsync(v1client2Scope);

            // let's try to sync firstly
            // Now test a new sync, on this new scope v1
            // Obviously, we don't have anything from the server
            var s5 = await agent2.SynchronizeAsync("v1", progress : progress);

            Console.WriteLine(s5);

            // If we get the row from client, we have the new column, but value remains null
            // since this row was synced before client migration
            client2row = await Helper.GetLastAddressRowAsync(client2Provider.CreateConnection(), addressId);

            Console.WriteLine(client2row);

            // What we can do here, is just make a sync with Renit
            var s6 = await agent2.SynchronizeAsync("v1", SyncType.ReinitializeWithUpload, progress : progress);

            Console.WriteLine($"Making a full Reinitialize sync on SQLite client2");
            Console.WriteLine(s6);

            // And now the row is correct
            // If we get the row from client, we have the new column, but value remains null
            // since this row was synced before client migration
            client2row = await Helper.GetLastAddressRowAsync(client2Provider.CreateConnection(), addressId);

            Console.WriteLine(client2row);


            // Migration done

            Console.WriteLine("End");
        }
Example #30
0
    public static async Task SyncHttpThroughKestellAsync()
    {
        // server provider
        // Create 2 Sql Sync providers
        var serverProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(serverDbName));
        var clientProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientDbName));


        // ----------------------------------
        // Client side
        // ----------------------------------
        var clientOptions = new SyncOptions {
            BatchSize = 500
        };

        var proxyClientProvider = new WebClientOrchestrator();

        // ----------------------------------
        // Web Server side
        // ----------------------------------
        var setup = new SyncSetup(allTables)
        {
            ScopeName = "all_tables_scope",
            StoredProceduresPrefix = "s",
            StoredProceduresSuffix = "",
            TrackingTablesPrefix   = "t",
            TrackingTablesSuffix   = "",
            TriggersPrefix         = "",
            TriggersSuffix         = "t"
        };

        // snapshot directory
        var directory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Snapshots");

        // ----------------------------------
        // Create a snapshot
        // ----------------------------------
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine($"Creating snapshot");
        var remoteOrchestrator = new RemoteOrchestrator(serverProvider);
        await remoteOrchestrator.CreateSnapshotAsync(new SyncContext(), setup, directory, 500, CancellationToken.None);

        Console.WriteLine($"Done.");
        Console.ResetColor();


        // ----------------------------------
        // Insert a value after snapshot created
        // ----------------------------------
        using (var c = serverProvider.CreateConnection())
        {
            var command = c.CreateCommand();
            command.CommandText = "INSERT INTO [dbo].[ProductCategory] ([Name]) VALUES ('Bikes revolution');";
            c.Open();
            command.ExecuteNonQuery();
            c.Close();
        }

        var webServerOptions = new WebServerOptions {
            SnapshotsDirectory = directory
        };

        // Creating an agent that will handle all the process
        var agent = new SyncAgent(clientProvider, proxyClientProvider);

        agent.Options = clientOptions;

        var configureServices = new Action <IServiceCollection>(services =>
        {
            services.AddSyncServer <SqlSyncProvider>(serverProvider.ConnectionString, setup, webServerOptions);
        });

        var serverHandler = new RequestDelegate(async context =>
        {
            var webProxyServer = context.RequestServices.GetService(typeof(WebProxyServerOrchestrator)) as WebProxyServerOrchestrator;
            await webProxyServer.HandleRequestAsync(context);
        });

        using (var server = new KestrellTestServer(configureServices))
        {
            var clientHandler = new ResponseDelegate(async(serviceUri) =>
            {
                proxyClientProvider.ServiceUri = serviceUri;
                do
                {
                    Console.Clear();
                    Console.WriteLine("Web sync start");
                    try
                    {
                        var progress = new SynchronousProgress <ProgressArgs>(pa => Console.WriteLine($"{pa.Context.SyncStage}\t {pa.Message}"));
                        var s        = await agent.SynchronizeAsync(progress);
                        Console.WriteLine(s);
                    }
                    catch (SyncException e)
                    {
                        Console.WriteLine(e.ToString());
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("UNKNOW EXCEPTION : " + e.Message);
                    }


                    Console.WriteLine("Sync Ended. Press a key to start again, or Escapte to end");
                } while (Console.ReadKey().Key != ConsoleKey.Escape);
            });
            await server.Run(serverHandler, clientHandler);
        }
    }