Exemplo n.º 1
0
        private static async Task DeprovisionServerManuallyAsync()
        {
            // Create server provider
            var serverProvider = new SqlSyncProvider(serverConnectionString);

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

            // Create a server orchestrator used to Deprovision everything on the server side
            var remoteOrchestrator = new RemoteOrchestrator(serverProvider, options, setup);

            // Get the server scope
            var serverScope = await remoteOrchestrator.GetServerScopeAsync();

            // Deprovision everything
            await remoteOrchestrator.DeprovisionAsync(SyncProvision.StoredProcedures
                                                      | SyncProvision.Triggers | SyncProvision.TrackingTable);

            // Affect good values
            serverScope.Setup  = null;
            serverScope.Schema = null;

            // save the server scope
            await remoteOrchestrator.SaveServerScopeAsync(serverScope);
        }
Exemplo n.º 2
0
        public void SyncAgent_EighthConstructor_LocalOrchestrator_ShouldMatch_RemoteOrchestrator_With_ScopeNameDefined()
        {
            var clientProvider = new SqlSyncProvider();
            var options        = new SyncOptions();
            var setup          = new SyncSetup(new string[] { "Customer" });

            // this options and setup will be overriden by the constructor
            var remoteOptions = new SyncOptions();
            var remoteSetup   = new SyncSetup(new string[] { "Product", "ProductCategory" });

            var remoteOrchestrator = new RemoteOrchestrator(new SqlSyncProvider(), remoteOptions, remoteSetup);

            var agent = new SyncAgent(clientProvider, remoteOrchestrator, options, setup, "CustomerScope");

            this.CheckConstructor(agent);
            Assert.Same(options, agent.LocalOrchestrator.Options);
            Assert.Same(options, agent.RemoteOrchestrator.Options);
            Assert.Same(setup, agent.LocalOrchestrator.Setup);
            Assert.Same(setup, agent.RemoteOrchestrator.Setup);
            Assert.Equal("CustomerScope", agent.ScopeName);
            Assert.Equal("CustomerScope", agent.LocalOrchestrator.ScopeName);
            Assert.Equal("CustomerScope", agent.RemoteOrchestrator.ScopeName);
            Assert.Single(agent.LocalOrchestrator.Setup.Tables);
            Assert.Single(agent.RemoteOrchestrator.Setup.Tables);
            Assert.Equal("Customer", agent.LocalOrchestrator.Setup.Tables[0].TableName);
            Assert.Equal("Customer", agent.RemoteOrchestrator.Setup.Tables[0].TableName);
        }
Exemplo n.º 3
0
        public async Task Trigger_Exists()
        {
            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);

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

            var options = new SyncOptions();
            var setup   = new SyncSetup(new string[] { "SalesLT.Product" });

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(setup);

            await remoteOrchestrator.CreateTriggerAsync(scopeInfo, "Product", "SalesLT", DbTriggerType.Insert);

            var exists = await remoteOrchestrator.ExistTriggerAsync(scopeInfo, "Product", "SalesLT", DbTriggerType.Insert);

            Assert.True(exists);

            exists = await remoteOrchestrator.ExistTriggerAsync(scopeInfo, "Product", "SalesLT", DbTriggerType.Update);

            Assert.False(exists);

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
Exemplo n.º 4
0
        private static async Task ProvisionClientManuallyAsync()
        {
            // Create 2 Sql Sync providers
            var serverProvider = new SqlSyncProvider(serverConnectionString);
            var clientProvider = new SqlSyncProvider(clientConnectionString);


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

            // This method is useful if you want to provision by yourself the client database
            // You will need to :
            // - Create a local orchestrator with the correct setup to provision
            // - Get the ServerScopeInfo from the server side using a RemoteOrchestrator or a WebRemoteOrchestrator
            // - Provision everything locally

            // Create a local orchestrator used to provision everything locally
            var localOrchestrator = new LocalOrchestrator(clientProvider);

            // Because we need the schema from remote side, create a remote orchestrator
            var remoteOrchestrator = new RemoteOrchestrator(serverProvider);

            // Getting the server scope from server side
            var serverScope = await remoteOrchestrator.GetServerScopeInfoAsync();

            // You can create a WebRemoteOrchestrator and get the ServerScope as well
            // var proxyClientProvider = new WebRemoteOrchestrator("https://localhost:44369/api/Sync");
            // var serverScope = proxyClientProvider.GetServerScopeInfoAsync();

            // Provision everything needed (sp, triggers, tracking tables, AND TABLES)
            await localOrchestrator.ProvisionAsync(serverScope);
        }
        public async Task RemoteOrchestrator_Provision_SchemaCreated_If_SetupHasTables()
        {
            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 scopeName = "scope";

            var options = new SyncOptions();
            var setup   = new SyncSetup(new string[] { "SalesLT.Product" });

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var provision = SyncProvision.Table | SyncProvision.TrackingTable | SyncProvision.StoredProcedures | SyncProvision.Triggers;

            var clientScopeInfo = await remoteOrchestrator.ProvisionAsync(scopeName, setup, provision);

            Assert.Single(clientScopeInfo.Schema.Tables);
            Assert.Equal("SalesLT.Product", clientScopeInfo.Schema.Tables[0].GetFullName());
            Assert.Equal(17, clientScopeInfo.Schema.Tables[0].Columns.Count);

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task RemoteOrchestrator_Provision_SchemaNotCreated_If_SetupHasTables_AndDbIsEmpty()
        {
            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 scopeName = "scope";

            var options = new SyncOptions();
            var setup   = new SyncSetup(new string[] { "SalesLT.Product" });

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var provision = SyncProvision.Table | SyncProvision.TrackingTable | SyncProvision.StoredProcedures | SyncProvision.Triggers;

            var se = await Assert.ThrowsAsync <SyncException>(
                async() => await remoteOrchestrator.ProvisionAsync(scopeName, setup, provision));

            Assert.Equal(SyncStage.Provisioning, se.SyncStage);
            Assert.Equal(SyncSide.ServerSide, se.Side);
            Assert.Equal("MissingTableException", se.TypeName);

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task RemoteOrchestrator_GetServerScopeInfo_NonExistingTables_ShouldFail()
        {
            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();
            // Create a bad setup with a non existing table

            var tables = new string[]
            {
                "SalesLT.ProductCategory", "SalesLT.ProductModel", "SalesLT.Product", "Employee", "Customer", "Address", "CustomerAddress", "EmployeeAddress",
                "SalesLT.SalesOrderHeader", "SalesLT.SalesOrderDetail", "Posts", "Tags", "PostTag",
                "PricesList", "PricesListCategory", "PricesListDetail", "WRONGTABLE"
            };
            var setup = new SyncSetup(tables);

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var se = await Assert.ThrowsAsync <SyncException>(async() =>
            {
                await remoteOrchestrator.GetServerScopeInfoAsync(setup);
            });

            Assert.Equal(SyncStage.Provisioning, se.SyncStage);
            Assert.Equal(SyncSide.ServerSide, se.Side);
            Assert.Equal("MissingTableException", se.TypeName);


            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task RemoteOrchestrator_Provision_ShouldFail_If_SetupIsEmpty()
        {
            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 scopeName = "scope";

            var options = new SyncOptions();
            var setup   = new SyncSetup();

            var orchestrator = new RemoteOrchestrator(sqlProvider, options);

            var provision = SyncProvision.Table | SyncProvision.TrackingTable | SyncProvision.StoredProcedures | SyncProvision.Triggers;

            var se = await Assert.ThrowsAsync <SyncException>(
                async() => await orchestrator.ProvisionAsync(scopeName, setup, provision));

            Assert.Equal(SyncStage.ScopeLoading, se.SyncStage);
            Assert.Equal(SyncSide.ServerSide, se.Side);
            Assert.Equal("MissingServerScopeTablesException", se.TypeName);

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task RemoteOrchestrator_GetServerScopeInfo_SetupColumnsDefined_ShouldReturn_SchemaWithSetupColumnsOnly()
        {
            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();
            // Create a bad setup with a non existing table

            var tables = new string[] { "Customer", "Address", "CustomerAddress" };
            var setup  = new SyncSetup(tables);

            setup.Tables["Customer"].Columns.AddRange(new string[] { "CustomerID", "FirstName", "LastName", "CompanyName" });

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(setup);

            Assert.Equal(3, scopeInfo.Schema.Tables.Count);

            // Only 4 columns shoud be part of Customer table
            Assert.Equal(4, scopeInfo.Schema.Tables["Customer"].Columns.Count);

            Assert.Equal(9, scopeInfo.Schema.Tables["Address"].Columns.Count);
            Assert.Equal(5, scopeInfo.Schema.Tables["CustomerAddress"].Columns.Count);

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task RemoteOrchestrator_GetServerScopeInfo_NonExistingColumns_ShouldFail()
        {
            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();
            // Create a bad setup with a non existing table

            var tables = new string[] { "Customer", "Address", "CustomerAddress" };
            var setup  = new SyncSetup(tables);

            setup.Tables["Customer"].Columns.AddRange(new string[] { "FirstName", "LastName", "CompanyName", "BADCOLUMN" });

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var se = await Assert.ThrowsAsync <SyncException>(async() =>
            {
                await remoteOrchestrator.GetServerScopeInfoAsync(setup);
            });

            Assert.Equal(SyncStage.Provisioning, se.SyncStage);
            Assert.Equal(SyncSide.ServerSide, se.Side);
            Assert.Equal("MissingColumnException", se.TypeName);


            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task RemoteOrchestrator_StoredProcedure_Exists()
        {
            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);

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

            var scopeName = "scope";

            var options = new SyncOptions();
            var setup   = new SyncSetup(new string[] { "SalesLT.Product" })
            {
                StoredProceduresPrefix = "sp_",
                StoredProceduresSuffix = "_sp"
            };

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(scopeName, setup);

            await remoteOrchestrator.CreateStoredProcedureAsync(scopeInfo, "Product", "SalesLT", DbStoredProcedureType.SelectChanges, false);

            Assert.True(await remoteOrchestrator.ExistStoredProcedureAsync(scopeInfo, "Product", "SalesLT", DbStoredProcedureType.SelectChanges));
            Assert.False(await remoteOrchestrator.ExistStoredProcedureAsync(scopeInfo, "Product", "SalesLT", DbStoredProcedureType.UpdateRow));

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task RemoteOrchestrator_Scope_IsNotNewScope_OnceSaved()
        {
            var dbName = HelperDatabase.GetRandomName("tcp_ro_");
            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 scopeName = "scope";

            var options = new SyncOptions();
            var setup   = new SyncSetup(this.Tables);

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var remoteScopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(scopeName, setup);

            Assert.True(remoteScopeInfo.IsNewScope);
            Assert.Equal(SyncVersion.Current, new Version(remoteScopeInfo.Version));

            remoteScopeInfo = await remoteOrchestrator.SaveServerScopeInfoAsync(remoteScopeInfo);

            Assert.False(remoteScopeInfo.IsNewScope);

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
Exemplo n.º 13
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);
        }
Exemplo n.º 14
0
        public override RemoteOrchestrator CreateRemoteOrchestrator(ProviderType providerType, string dbName)
        {
            var cs           = HelperDatabase.GetConnectionString(ProviderType.MySql, dbName);
            var orchestrator = new RemoteOrchestrator(new MySqlSyncProvider(cs));

            return(orchestrator);
        }
Exemplo n.º 15
0
    private static async Task CreateSnapshotAsync()
    {
        // Create 2 Sql Sync providers
        var serverProvider = new SqlSyncProvider(DBHelper.GetDatabaseConnectionString(serverDbName));

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

        // 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();
        });

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

        var options = new SyncOptions
        {
            SnapshotsDirectory = directory,
            BatchSize          = 2000
        };

        var remoteOrchestrator = new RemoteOrchestrator(serverProvider, options, setup);

        await remoteOrchestrator.CreateSnapshotAsync(null, default, remoteProgress);
        public async Task Table_Drop_All()
        {
            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 setup   = new SyncSetup(this.Tables);

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var onDropping = 0;
            var onDropped  = 0;

            var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(setup);

            remoteOrchestrator.OnTableDropping(ttca => onDropping++);
            remoteOrchestrator.OnTableDropped(ttca => onDropped++);

            await remoteOrchestrator.DropTablesAsync(scopeInfo);

            Assert.Equal(this.Tables.Length, onDropping);
            Assert.Equal(this.Tables.Length, onDropped);

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task RemoteOrchestrator_Provision_ShouldFails_If_SetupTable_DoesNotExist()
        {
            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 scopeName = "scope";

            var options = new SyncOptions();
            var setup   = new SyncSetup(new string[] { "SalesLT.badTable" });

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var se = await Assert.ThrowsAsync <SyncException>(async() =>
                                                              await remoteOrchestrator.GetServerScopeInfoAsync(scopeName, setup));

            Assert.Equal(SyncStage.Provisioning, se.SyncStage);
            Assert.Equal(SyncSide.ServerSide, se.Side);
            Assert.Equal("MissingTableException", se.TypeName);

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task RemoteOrchestrator_Provision_ShouldCreate_StoredProcedures_WithSpecificScopeName()
        {
            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);
            // Create default table
            var ctx = new AdventureWorksContext((dbName, ProviderType.Sql, sqlProvider), true, false);
            await ctx.Database.EnsureCreatedAsync();

            var scopeName = "scope";

            var options = new SyncOptions();
            var setup   = new SyncSetup(new string[] { "SalesLT.Product" })
            {
                StoredProceduresPrefix = "s",
                StoredProceduresSuffix = "proc"
            };

            // trackign table name is composed with prefix and suffix from setup
            var bulkDelete     = $"SalesLT.{setup.StoredProceduresPrefix}Product{setup.StoredProceduresSuffix}_{scopeName}_bulkdelete";
            var bulkUpdate     = $"SalesLT.{setup.StoredProceduresPrefix}Product{setup.StoredProceduresSuffix}_{scopeName}_bulkupdate";
            var changes        = $"SalesLT.{setup.StoredProceduresPrefix}Product{setup.StoredProceduresSuffix}_{scopeName}_changes";
            var delete         = $"SalesLT.{setup.StoredProceduresPrefix}Product{setup.StoredProceduresSuffix}_{scopeName}_delete";
            var deletemetadata = $"SalesLT.{setup.StoredProceduresPrefix}Product{setup.StoredProceduresSuffix}_{scopeName}_deletemetadata";
            var initialize     = $"SalesLT.{setup.StoredProceduresPrefix}Product{setup.StoredProceduresSuffix}_{scopeName}_initialize";
            var reset          = $"SalesLT.{setup.StoredProceduresPrefix}Product{setup.StoredProceduresSuffix}_{scopeName}_reset";
            var selectrow      = $"SalesLT.{setup.StoredProceduresPrefix}Product{setup.StoredProceduresSuffix}_{scopeName}_selectrow";
            var update         = $"SalesLT.{setup.StoredProceduresPrefix}Product{setup.StoredProceduresSuffix}_{scopeName}_update";

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            // Needs the tracking table to be able to create stored procedures
            var provision = SyncProvision.TrackingTable | SyncProvision.StoredProcedures;

            var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(scopeName, setup);

            await remoteOrchestrator.ProvisionAsync(scopeInfo, provision);

            using (var connection = new SqlConnection(cs))
            {
                await connection.OpenAsync().ConfigureAwait(false);

                Assert.True(await SqlManagementUtils.ProcedureExistsAsync(connection, null, bulkDelete));
                Assert.True(await SqlManagementUtils.ProcedureExistsAsync(connection, null, bulkUpdate));
                Assert.True(await SqlManagementUtils.ProcedureExistsAsync(connection, null, changes));
                Assert.True(await SqlManagementUtils.ProcedureExistsAsync(connection, null, delete));
                Assert.True(await SqlManagementUtils.ProcedureExistsAsync(connection, null, deletemetadata));
                Assert.True(await SqlManagementUtils.ProcedureExistsAsync(connection, null, initialize));
                Assert.True(await SqlManagementUtils.ProcedureExistsAsync(connection, null, reset));
                Assert.True(await SqlManagementUtils.ProcedureExistsAsync(connection, null, selectrow));
                Assert.True(await SqlManagementUtils.ProcedureExistsAsync(connection, null, update));

                connection.Close();
            }

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task TrackingTable_Create_One()
        {
            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 setup = new SyncSetup(new string[] { "SalesLT.Product" })
            {
                TrackingTablesPrefix = "t_",
                TrackingTablesSuffix = "_t"
            };

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(setup);

            var onCreating = false;
            var onCreated  = false;

            remoteOrchestrator.OnTrackingTableCreating(ttca =>
            {
                var addingID              = $" ALTER TABLE {ttca.TrackingTableName.Schema().Quoted()} ADD internal_id int identity(1,1)";
                ttca.Command.CommandText += addingID;
                onCreating = true;
            });

            remoteOrchestrator.OnTrackingTableCreated(ttca =>
            {
                onCreated = true;
            });

            await remoteOrchestrator.CreateTrackingTableAsync(scopeInfo, "Product", "SalesLT");

            Assert.True(onCreating);
            Assert.True(onCreated);


            // Check we have a new column in tracking table
            using (var c = new SqlConnection(cs))
            {
                await c.OpenAsync().ConfigureAwait(false);

                var cols = await SqlManagementUtils.GetColumnsForTableAsync(c, null, "t_Product_t", "SalesLT").ConfigureAwait(false);

                Assert.Equal(7, cols.Rows.Count);
                Assert.NotNull(cols.Rows.FirstOrDefault(r => r["name"].ToString() == "internal_id"));
                c.Close();
            }

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
Exemplo n.º 20
0
        public async Task Trigger_Create_One()
        {
            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);

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

            var options = new SyncOptions();
            var setup   = new SyncSetup(new string[] { "SalesLT.Product" });

            // 1) create a console logger
            //var loggerFactory = LoggerFactory.Create(builder => { builder.AddDebug().SetMinimumLevel(LogLevel.Debug); });
            //var logger = loggerFactory.CreateLogger("Dotmim.Sync");
            var logger = new SyncLogger().AddDebug().SetMinimumLevel(LogLevel.Debug);

            options.Logger = logger;

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(setup);

            var onCreating = 0;
            var onCreated  = 0;
            var onDropping = 0;
            var onDropped  = 0;

            remoteOrchestrator.OnTriggerCreating(tca => onCreating++);
            remoteOrchestrator.OnTriggerCreated(tca => onCreated++);
            remoteOrchestrator.OnTriggerDropping(tca => onDropping++);
            remoteOrchestrator.OnTriggerDropped(tca => onDropped++);

            var isCreated = await remoteOrchestrator.CreateTriggerAsync(scopeInfo, "Product", "SalesLT", DbTriggerType.Insert);

            Assert.True(isCreated);
            Assert.Equal(1, onCreating);
            Assert.Equal(1, onCreated);
            Assert.Equal(0, onDropping);
            Assert.Equal(0, onDropped);

            // Check
            using (var c = new SqlConnection(cs))
            {
                await c.OpenAsync().ConfigureAwait(false);

                var check = await SqlManagementUtils.GetTriggerAsync(c, null, "Product_insert_trigger", "SalesLT").ConfigureAwait(false);

                Assert.Single(check.Rows);
                c.Close();
            }

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
Exemplo n.º 21
0
        private static async Task DropSync()
        {
            var provider     = new SqlSyncProvider(serverConnectionString);
            var options      = new SyncOptions();
            var setup        = new SyncSetup("ProductCategory", "ProductModel", "Product");
            var orchestrator = new RemoteOrchestrator(provider, options);

            await orchestrator.DropAllAsync();
        }
Exemplo n.º 22
0
        public async Task Trigger_Create_All()
        {
            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);

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

            var options = new SyncOptions();
            var setup   = new SyncSetup(new string[] { "SalesLT.Product" });

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(setup);

            var onCreating = 0;
            var onCreated  = 0;
            var onDropping = 0;
            var onDropped  = 0;

            remoteOrchestrator.OnTriggerCreating(tca => onCreating++);
            remoteOrchestrator.OnTriggerCreated(tca => onCreated++);
            remoteOrchestrator.OnTriggerDropping(tca => onDropping++);
            remoteOrchestrator.OnTriggerDropped(tca => onDropped++);

            var isCreated = await remoteOrchestrator.CreateTriggersAsync(scopeInfo, "Product", "SalesLT");

            Assert.True(isCreated);
            Assert.Equal(3, onCreating);
            Assert.Equal(3, onCreated);
            Assert.Equal(0, onDropping);
            Assert.Equal(0, onDropped);

            // Check
            using (var c = new SqlConnection(cs))
            {
                await c.OpenAsync().ConfigureAwait(false);

                var check = await SqlManagementUtils.GetTriggerAsync(c, null, "Product_insert_trigger", "SalesLT").ConfigureAwait(false);

                Assert.Single(check.Rows);
                check = await SqlManagementUtils.GetTriggerAsync(c, null, "Product_update_trigger", "SalesLT").ConfigureAwait(false);

                Assert.Single(check.Rows);
                check = await SqlManagementUtils.GetTriggerAsync(c, null, "Product_delete_trigger", "SalesLT").ConfigureAwait(false);

                Assert.Single(check.Rows);
                c.Close();
            }


            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task RemoteOrchestrator_Provision_ShouldCreate_Triggers()
        {
            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);
            // Create default table
            var ctx = new AdventureWorksContext((dbName, ProviderType.Sql, sqlProvider), true, false);
            await ctx.Database.EnsureCreatedAsync();

            var scopeName = "scope";

            var options = new SyncOptions();
            var setup   = new SyncSetup(new string[] { "SalesLT.Product" })
            {
                TrackingTablesSuffix = "sync",
                TrackingTablesPrefix = "trck",
                TriggersPrefix       = "trg_",
                TriggersSuffix       = "_trg"
            };

            // trackign table name is composed with prefix and suffix from setup
            var triggerDelete = $"{setup.TriggersPrefix}Product{setup.TriggersSuffix}_delete_trigger";
            var triggerInsert = $"{setup.TriggersPrefix}Product{setup.TriggersSuffix}_insert_trigger";
            var triggerUpdate = $"{setup.TriggersPrefix}Product{setup.TriggersSuffix}_update_trigger";

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);
            var scopeInfo          = await remoteOrchestrator.GetServerScopeInfoAsync(scopeName, setup);

            // Needs the tracking table to be able to create triggers
            var provision = SyncProvision.TrackingTable | SyncProvision.Triggers;

            await remoteOrchestrator.ProvisionAsync(scopeInfo, provision);

            using (var c = new SqlConnection(cs))
            {
                await c.OpenAsync().ConfigureAwait(false);

                var trigDel = await SqlManagementUtils.GetTriggerAsync(c, null, triggerDelete, "SalesLT");

                Assert.Equal(triggerDelete, trigDel.Rows[0]["Name"].ToString());

                var trigIns = await SqlManagementUtils.GetTriggerAsync(c, null, triggerInsert, "SalesLT");

                Assert.Equal(triggerInsert, trigIns.Rows[0]["Name"].ToString());

                var trigUdate = await SqlManagementUtils.GetTriggerAsync(c, null, triggerUpdate, "SalesLT");

                Assert.Equal(triggerUpdate, trigUdate.Rows[0]["Name"].ToString());

                c.Close();
            }

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task TrackingTable_Drop_One_Cancel()
        {
            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 setup   = new SyncSetup(new string[] { "SalesLT.Product" });

            setup.TrackingTablesPrefix = "t_";
            setup.TrackingTablesSuffix = "_t";

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(setup);

            var onDropping = false;
            var onDropped  = false;

            remoteOrchestrator.OnTrackingTableDropping(ttca =>
            {
                ttca.Cancel = true;
                onDropping  = true;
            });

            remoteOrchestrator.OnTrackingTableDropped(ttca =>
            {
                onDropped = true;
            });

            await remoteOrchestrator.CreateTrackingTableAsync(scopeInfo, "Product", "SalesLT");

            await remoteOrchestrator.DropTrackingTableAsync(scopeInfo, "Product", "SalesLT");

            Assert.True(onDropping);
            Assert.False(onDropped);

            // Check we have a new column in tracking table
            using (var c = new SqlConnection(cs))
            {
                await c.OpenAsync().ConfigureAwait(false);

                var table = await SqlManagementUtils.GetTableAsync(c, null, "t_Product_t", "SalesLT").ConfigureAwait(false);

                Assert.NotEmpty(table.Rows);

                c.Close();
            }

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
        public async Task RemoteOrchestrator_GetServerScopeInfo_ShouldReturnSchema()
        {
            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 scopeName = "scope";

            var options = new SyncOptions();
            var setup   = new SyncSetup(this.Tables);

            var onSchemaRead    = false;
            var onSchemaReading = false;

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            remoteOrchestrator.OnSchemaLoading(args =>
            {
                Assert.Equal(scopeName, args.Context.ScopeName);
                onSchemaReading = true;
            });

            remoteOrchestrator.OnSchemaLoaded(args =>
            {
                Assert.IsType <SchemaLoadedArgs>(args);
                Assert.Equal(SyncStage.Provisioning, args.Context.SyncStage);
                Assert.Equal(scopeName, args.Context.ScopeName);
                Assert.NotNull(args.Connection);
                Assert.Null(args.Transaction);
                Assert.Equal(ConnectionState.Open, args.Connection.State);
                Assert.Equal(16, args.Schema.Tables.Count);
                onSchemaRead = true;
            });

            AssertConnectionAndTransaction(remoteOrchestrator, scopeName);

            var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(scopeName, setup);

            Assert.NotNull(scopeInfo.Schema);
            Assert.NotNull(scopeInfo.Setup);
            Assert.Equal(16, scopeInfo.Schema.Tables.Count);
            Assert.True(onSchemaRead);
            Assert.True(onSchemaReading);

            var schema = await remoteOrchestrator.GetSchemaAsync(scopeName, setup);

            Assert.NotNull(schema);
            Assert.Equal(16, schema.Tables.Count);


            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
Exemplo n.º 26
0
        public async Task RemoteOrchestrator_GetEstimatedChanges_BeforeInitialize_ShouldReturnRowsCount()
        {
            var dbNameSrv = HelperDatabase.GetRandomName("tcp_lo_srv");
            await HelperDatabase.CreateDatabaseAsync(ProviderType.Sql, dbNameSrv, true);

            var csServer       = HelperDatabase.GetConnectionString(ProviderType.Sql, dbNameSrv);
            var serverProvider = new SqlSyncProvider(csServer);

            await new AdventureWorksContext((dbNameSrv, ProviderType.Sql, serverProvider), true, false).Database.EnsureCreatedAsync();

            var scopeName   = "scopesnap1";
            var syncOptions = new SyncOptions();
            var setup       = new SyncSetup();

            var remoteOrchestrator = new RemoteOrchestrator(serverProvider, new SyncOptions(), new SyncSetup(this.Tables), scopeName);

            // Server side : Create a product category and a product
            // Create a productcategory item
            // Create a new product on server
            var productId     = Guid.NewGuid();
            var productName   = HelperDatabase.GetRandomName();
            var productNumber = productName.ToUpperInvariant().Substring(0, 10);

            var productCategoryName = HelperDatabase.GetRandomName();
            var productCategoryId   = productCategoryName.ToUpperInvariant().Substring(0, 6);

            using (var ctx = new AdventureWorksContext((dbNameSrv, ProviderType.Sql, serverProvider)))
            {
                var pc = new ProductCategory {
                    ProductCategoryId = productCategoryId, Name = productCategoryName
                };
                ctx.Add(pc);

                var product = new Product {
                    ProductId = productId, Name = productName, ProductNumber = productNumber
                };
                ctx.Add(product);

                await ctx.SaveChangesAsync();
            }

            // fake client scope
            var clientScope = new ScopeInfo()
            {
                Name = scopeName, IsNewScope = true
            };

            // Get estimated changes count to be sent to the client
            var changes = await remoteOrchestrator.GetEstimatedChangesCountAsync(clientScope);

            Assert.NotNull(changes.ServerChangesSelected);
            Assert.Equal(2, changes.ServerChangesSelected.TableChangesSelected.Count);
            Assert.Contains("Product", changes.ServerChangesSelected.TableChangesSelected.Select(tcs => tcs.TableName).ToList());
            Assert.Contains("ProductCategory", changes.ServerChangesSelected.TableChangesSelected.Select(tcs => tcs.TableName).ToList());
        }
Exemplo n.º 27
0
        public async Task <IActionResult> CreateSnapshotAsync()
        {
            var connectionString = configuration.GetConnectionString("DefaultConnection");
            var serverProvider   = new SqlSyncProvider(connectionString);
            // Create a remote orchestrator
            var remoteOrchestrator = new RemoteOrchestrator(serverProvider, syncOptions, syncSetup);
            // Create a snapshot
            await remoteOrchestrator.CreateSnapshotAsync();

            return(Ok());
        }
Exemplo n.º 28
0
        public async Task Trigger_Drop_All()
        {
            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);

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

            var options = new SyncOptions();
            var setup   = new SyncSetup(new string[] { "SalesLT.Product" });

            var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options);

            var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(setup);

            var onCreating = 0;
            var onCreated  = 0;
            var onDropping = 0;
            var onDropped  = 0;

            remoteOrchestrator.OnTriggerCreating(tca => onCreating++);
            remoteOrchestrator.OnTriggerCreated(tca => onCreated++);
            remoteOrchestrator.OnTriggerDropping(tca => onDropping++);
            remoteOrchestrator.OnTriggerDropped(tca => onDropped++);

            var isCreated = await remoteOrchestrator.CreateTriggersAsync(scopeInfo, "Product", "SalesLT");

            Assert.True(isCreated);
            Assert.Equal(3, onCreating);
            Assert.Equal(3, onCreated);
            Assert.Equal(0, onDropping);
            Assert.Equal(0, onDropped);


            onCreating = 0;
            onCreated  = 0;
            onDropping = 0;
            onDropped  = 0;

            var isDropped = await remoteOrchestrator.DropTriggersAsync(scopeInfo, "Product", "SalesLT");

            Assert.True(isCreated);
            Assert.Equal(0, onCreating);
            Assert.Equal(0, onCreated);
            Assert.Equal(3, onDropping);
            Assert.Equal(3, onDropped);


            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
Exemplo n.º 29
0
        public async Task RemoteOrchestrator_CreateSnapshot_ShouldFail_If_MissingMandatoriesOptions()
        {
            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, true);
            await ctx.Database.EnsureCreatedAsync();

            var scopeName = "scopesnap";

            // snapshot directory
            var snapshotDirctoryName = HelperDatabase.GetRandomName();
            var snapshotDirectory    = Path.Combine(Environment.CurrentDirectory, snapshotDirctoryName);

            var options = new SyncOptions {
                SnapshotsDirectory = snapshotDirectory
            };

            var setup    = new SyncSetup(Tables);
            var provider = new SqlSyncProvider(cs);

            var orchestrator = new RemoteOrchestrator(provider, options, setup, scopeName);
            var se           = await Assert.ThrowsAsync <SyncException>(() => orchestrator.CreateSnapshotAsync());

            Assert.Equal(SyncStage.SnapshotCreating, se.SyncStage);
            Assert.Equal(SyncSide.ServerSide, se.Side);
            Assert.Equal("SnapshotMissingMandatariesOptionsException", se.TypeName);

            options = new SyncOptions {
                BatchSize = 2000
            };
            orchestrator = new RemoteOrchestrator(provider, options, setup, scopeName);
            se           = await Assert.ThrowsAsync <SyncException>(() => orchestrator.CreateSnapshotAsync());

            Assert.Equal(SyncStage.SnapshotCreating, se.SyncStage);
            Assert.Equal(SyncSide.ServerSide, se.Side);
            Assert.Equal("SnapshotMissingMandatariesOptionsException", se.TypeName);

            options      = new SyncOptions {
            };
            orchestrator = new RemoteOrchestrator(provider, options, setup, scopeName);
            se           = await Assert.ThrowsAsync <SyncException>(() => orchestrator.CreateSnapshotAsync());

            Assert.Equal(SyncStage.SnapshotCreating, se.SyncStage);
            Assert.Equal(SyncSide.ServerSide, se.Side);
            Assert.Equal("SnapshotMissingMandatariesOptionsException", se.TypeName);

            HelperDatabase.DropDatabase(ProviderType.Sql, dbName);
        }
Exemplo n.º 30
0
        private static async Task ProvisionClientManuallyAsync()
        {
            // 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();

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

            // This method is useful if you want to provision by yourself the client database
            // You will need to :
            // - Create a local orchestrator with the correct setup to provision
            // - Get the local scope that will contains after provisioning, the serialized version of your scope / schema
            // - Get the schema from the server side using a RemoteOrchestrator or a WebClientOrchestrator
            // - Provision everything locally
            // - Save the local scope information

            // Create a local orchestrator used to provision everything locally
            var localOrchestrator = new LocalOrchestrator(clientProvider, options, setup);

            // Because we need the schema from remote side, create a remote orchestrator
            var remoteOrchestrator = new RemoteOrchestrator(serverProvider, options, setup);

            // Getting the schema from server side
            var serverSchema = await remoteOrchestrator.GetSchemaAsync();

            // 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 serverSchema = proxyClientProvider.GetSchemaAsync();

            // get the local scope
            var clientScope = await localOrchestrator.GetClientScopeAsync();

            // Provision everything needed (sp, triggers, tracking tables, AND TABLES)
            await localOrchestrator.ProvisionAsync(serverSchema, SyncProvision.StoredProcedures
                                                   | SyncProvision.Triggers | SyncProvision.TrackingTable | SyncProvision.Table);

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

            // save the client scope
            await localOrchestrator.SaveClientScopeAsync(clientScope);
        }