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 localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var onDropping = 0; var onDropped = 0; localOrchestrator.OnTableDropping(ttca => onDropping++); localOrchestrator.OnTableDropped(ttca => onDropped++); await localOrchestrator.DropTablesAsync(); Assert.Equal(this.Tables.Length, onDropping); Assert.Equal(this.Tables.Length, onDropped); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task BaseOrchestrator_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 localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup, scopeName); var provision = SyncProvision.Table | SyncProvision.TrackingTable | SyncProvision.StoredProcedures | SyncProvision.Triggers; var se = await Assert.ThrowsAsync <SyncException>(async() => await localOrchestrator.ProvisionAsync(provision)); Assert.Equal(SyncStage.Provisioning, se.SyncStage); Assert.Equal(SyncSide.ClientSide, se.Side); Assert.Equal("MissingTableException", se.TypeName); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task RemoteOrchestrator_GetServerScopeInfo_NoPrimaryKeysColumn_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" }); var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options); var se = await Assert.ThrowsAsync <SyncException>(async() => { var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(setup); }); Assert.Equal(SyncStage.Provisioning, se.SyncStage); Assert.Equal(SyncSide.ServerSide, se.Side); Assert.Equal("MissingPrimaryKeyColumnException", 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 LocalOrchestrator_EnsureScope_NewScope_WithoutSetup_ShouldBeEmpty() { 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 localOrchestrator = new LocalOrchestrator(sqlProvider, options); var localScopeInfo = await localOrchestrator.GetClientScopeInfoAsync(scopeName); Assert.NotNull(localScopeInfo); Assert.Equal(scopeName, localScopeInfo.Name); Assert.True(localScopeInfo.IsNewScope); Assert.NotEqual(Guid.Empty, localScopeInfo.Id); Assert.Null(localScopeInfo.LastServerSyncTimestamp); Assert.Null(localScopeInfo.LastSync); Assert.Equal(0, localScopeInfo.LastSyncDuration); Assert.Null(localScopeInfo.LastSyncTimestamp); Assert.Null(localScopeInfo.Schema); Assert.Null(localScopeInfo.Setup); Assert.Equal(SyncVersion.Current, new Version(localScopeInfo.Version)); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task LocalOrchestrator_CancellationToken_ShouldInterrupt_EnsureScope_OnConnectionOpened() { 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 localOrchestrator = new LocalOrchestrator(sqlProvider, options); using var cts = new CancellationTokenSource(); localOrchestrator.OnConnectionOpen(args => cts.Cancel()); var se = await Assert.ThrowsAsync <SyncException>( async() => await localOrchestrator.GetClientScopeInfoAsync(cancellationToken: cts.Token)); Assert.Equal(SyncSide.ClientSide, se.Side); Assert.Equal("OperationCanceledException", 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 Table_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); var options = new SyncOptions(); var setup = new SyncSetup(new string[] { "SalesLT.Product", "SalesLT.ProductCategory" }); var table = new SyncTable("Product", "SalesLT"); var colID = new SyncColumn("ID", typeof(Guid)); var colName = new SyncColumn("Name", typeof(string)); table.Columns.Add(colID); table.Columns.Add(colName); table.Columns.Add("Number", typeof(int)); table.PrimaryKeys.Add("ID"); var localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); await localOrchestrator.CreateTableAsync(table); var exists = await localOrchestrator.ExistTableAsync(setup.Tables[0]).ConfigureAwait(false); Assert.True(exists); exists = await localOrchestrator.ExistTableAsync(setup.Tables[1]).ConfigureAwait(false); Assert.False(exists); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task StoredProcedure_Drop_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" }); var localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var isCreated = await localOrchestrator.CreateStoredProcedureAsync(setup.Tables["Product", "SalesLT"], DbStoredProcedureType.SelectChanges); Assert.True(isCreated); // Ensuring we have a clean new instance localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var onCreating = 0; var onCreated = 0; var onDropping = 0; var onDropped = 0; localOrchestrator.OnStoredProcedureCreating(tca => onCreating++); localOrchestrator.OnStoredProcedureCreated(tca => onCreated++); localOrchestrator.OnStoredProcedureDropping(tca => onDropping++); localOrchestrator.OnStoredProcedureDropped(tca => onDropped++); var isDropped = await localOrchestrator.DropStoredProcedureAsync(setup.Tables["Product", "SalesLT"], DbStoredProcedureType.SelectChanges); Assert.True(isDropped); Assert.Equal(0, onCreating); Assert.Equal(0, onCreated); Assert.Equal(1, onDropping); Assert.Equal(1, onDropped); // Check using (var c = new SqlConnection(cs)) { await c.OpenAsync().ConfigureAwait(false); var check = await SqlManagementUtils.ProcedureExistsAsync(c, null, "SalesLT.Product_changes").ConfigureAwait(false); Assert.False(check); c.Close(); } // try to delete a non existing one isDropped = await localOrchestrator.DropStoredProcedureAsync(setup.Tables["Product", "SalesLT"], DbStoredProcedureType.SelectChangesWithFilters); Assert.False(isDropped); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task BaseOrchestrator_GetSchema_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 localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var schema = await localOrchestrator.GetSchemaAsync(); Assert.Equal(SyncStage.SchemaReading, localOrchestrator.GetContext().SyncStage); Assert.Equal(3, schema.Tables.Count); // Only 4 columns shoud be part of Customer table Assert.Equal(4, schema.Tables["Customer"].Columns.Count); Assert.Equal(9, schema.Tables["Address"].Columns.Count); Assert.Equal(5, schema.Tables["CustomerAddress"].Columns.Count); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task TrackingTable_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(new string[] { "SalesLT.ProductCategory", "SalesLT.ProductModel", "SalesLT.Product", "dbo.Sql", "Posts" }); setup.TrackingTablesPrefix = "t_"; setup.TrackingTablesSuffix = "_t"; var localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var onDropping = 0; var onDropped = 0; localOrchestrator.OnTrackingTableDropping(ttca => onDropping++); localOrchestrator.OnTrackingTableDropped(ttca => onDropped++); await localOrchestrator.CreateTrackingTablesAsync(); await localOrchestrator.DropTrackingTablesAsync(); Assert.Equal(5, onDropping); Assert.Equal(5, onDropped); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task TrackingTable_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); 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", "SalesLT.ProductCategory" }); setup.TrackingTablesPrefix = "t_"; setup.TrackingTablesSuffix = "_t"; var localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); await localOrchestrator.CreateTrackingTableAsync(setup.Tables[0]); var exists = await localOrchestrator.ExistTrackingTableAsync(setup.Tables[0]); Assert.True(exists); exists = await localOrchestrator.ExistTrackingTableAsync(setup.Tables[1]); Assert.False(exists); 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); }
public async Task LocalTimestamp() { 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 localOrchestrator = new LocalOrchestrator(sqlProvider, options); var onLTLoading = 0; var onLTLoaded = 0; localOrchestrator.OnLocalTimestampLoading(tca => onLTLoading++); localOrchestrator.OnLocalTimestampLoaded(tca => onLTLoaded++); var ts = await localOrchestrator.GetLocalTimestampAsync(); Assert.Equal(1, onLTLoading); Assert.Equal(1, onLTLoaded); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task BaseOrchestrator_GetSchema_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", "dbo.Sql", "Posts", "Tags", "PostTag", "PricesList", "PricesListCategory", "PricesListDetail", "WRONGTABLE" }; var setup = new SyncSetup(tables); var localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var se = await Assert.ThrowsAsync <SyncException>(async() => { var schema = await localOrchestrator.GetSchemaAsync(); }); Assert.Equal(SyncStage.SchemaReading, se.SyncStage); Assert.Equal(SyncSide.ClientSide, se.Side); Assert.Equal("MissingTableException", se.TypeName); 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 Trigger_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); // 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 localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var isCreated = await localOrchestrator.CreateTriggerAsync(setup.Tables["Product", "SalesLT"], DbTriggerType.Insert); Assert.True(isCreated); // Ensuring we have a clean new instance localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var onCreating = 0; var onCreated = 0; var onDropping = 0; var onDropped = 0; localOrchestrator.OnTriggerCreating(tca => onCreating++); localOrchestrator.OnTriggerCreated(tca => onCreated++); localOrchestrator.OnTriggerDropping(tca => { tca.Cancel = true; onDropping++; }); localOrchestrator.OnTriggerDropped(tca => onDropped++); var isDropped = await localOrchestrator.DropTriggerAsync(setup.Tables["Product", "SalesLT"], DbTriggerType.Insert); Assert.False(isDropped); Assert.Equal(0, onCreating); Assert.Equal(0, onCreated); Assert.Equal(1, 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); }
public async Task RemoteOrchestrator_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 scopeName = "scope"; var options = new SyncOptions(); var setup = new SyncSetup(new string[] { "SalesLT.Product" }) { TriggersPrefix = "trg_", TriggersSuffix = "_trg" }; var remoteOrchestrator = new RemoteOrchestrator(sqlProvider, options); var scopeInfo = await remoteOrchestrator.GetServerScopeInfoAsync(scopeName, setup); await remoteOrchestrator.CreateTriggerAsync(scopeInfo, "Product", "SalesLT", DbTriggerType.Insert, false); var insertExists = await remoteOrchestrator.ExistTriggerAsync(scopeInfo, "Product", "SalesLT", DbTriggerType.Insert); var updateExists = await remoteOrchestrator.ExistTriggerAsync(scopeInfo, "Product", "SalesLT", DbTriggerType.Update); Assert.True(insertExists); Assert.False(updateExists); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task Create_Database_Should_Work() { var dbName = HelperDatabase.GetRandomName("Y"); var provider = this.CreateProvider(this.ProviderType, dbName); await provider.EnsureCreatedAsync(); var cs = HelperDatabase.GetConnectionString(this.ProviderType, dbName); // fun new C#8 using notation using var client = new CosmosClient(cs); var database = client.GetDatabase(dbName); var response = await database.ReadAsync(); Assert.Equal(HttpStatusCode.OK, response.StatusCode); // Default container has the same name as database var container = database.GetContainer(dbName); var containerResponse = await container.ReadContainerAsync(); Assert.Equal(HttpStatusCode.OK, containerResponse.StatusCode); var deleteDatabase = await database.DeleteAsync(); Assert.Equal(HttpStatusCode.OK, deleteDatabase.StatusCode); }
public async Task BaseOrchestrator_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 localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup, scopeName); var provision = SyncProvision.Table | SyncProvision.TrackingTable | SyncProvision.StoredProcedures | SyncProvision.Triggers; var schema = await localOrchestrator.ProvisionAsync(provision); var context = localOrchestrator.GetContext(); Assert.Equal(SyncStage.Provisioning, context.SyncStage); Assert.Single(schema.Tables); Assert.Equal("SalesLT.Product", schema.Tables[0].GetFullName()); Assert.Equal(17, schema.Tables[0].Columns.Count); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task BaseOrchestrator_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 localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup, scopeName); var provision = SyncProvision.Table | SyncProvision.TrackingTable | SyncProvision.StoredProcedures | SyncProvision.Triggers; var se = await Assert.ThrowsAsync <SyncException>(async() => await localOrchestrator.ProvisionAsync(provision)); Assert.Equal(SyncStage.Provisioning, se.SyncStage); Assert.Equal(SyncSide.ClientSide, se.Side); Assert.Equal("MissingTableException", se.TypeName); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task BaseOrchestrator_GetSchema_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 localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var se = await Assert.ThrowsAsync <SyncException>(async() => { var schema = await localOrchestrator.GetSchemaAsync(); }); Assert.Equal(SyncStage.SchemaReading, se.SyncStage); Assert.Equal(SyncSide.ClientSide, se.Side); Assert.Equal("MissingColumnException", se.TypeName); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
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 localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var isCreated = await localOrchestrator.CreateTriggerAsync(setup.Tables["Product", "SalesLT"], DbTriggerType.Insert); var exists = await localOrchestrator.ExistTriggerAsync(setup.Tables["Product", "SalesLT"], DbTriggerType.Insert); Assert.True(exists); exists = await localOrchestrator.ExistTriggerAsync(setup.Tables["Product", "SalesLT"], DbTriggerType.Update); Assert.False(exists); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task Trigger_Create_One_Overwrite() { 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 localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var onCreating = 0; var onCreated = 0; var onDropping = 0; var onDropped = 0; localOrchestrator.OnTriggerCreating(tca => onCreating++); localOrchestrator.OnTriggerCreated(tca => onCreated++); localOrchestrator.OnTriggerDropping(tca => onDropping++); localOrchestrator.OnTriggerDropped(tca => onDropped++); var isCreated = await localOrchestrator.CreateTriggerAsync(setup.Tables["Product", "SalesLT"], DbTriggerType.Insert); Assert.True(isCreated); Assert.Equal(1, onCreating); Assert.Equal(1, onCreated); Assert.Equal(0, onDropping); Assert.Equal(0, onDropped); onCreating = 0; onCreated = 0; onDropping = 0; onDropped = 0; isCreated = await localOrchestrator.CreateTriggerAsync(setup.Tables["Product", "SalesLT"], DbTriggerType.Insert); Assert.False(isCreated); Assert.Equal(0, onCreating); Assert.Equal(0, onCreated); Assert.Equal(0, onDropping); Assert.Equal(0, onDropped); isCreated = await localOrchestrator.CreateTriggerAsync(setup.Tables["Product", "SalesLT"], DbTriggerType.Insert, true); Assert.True(isCreated); Assert.Equal(1, onCreating); Assert.Equal(1, onCreated); Assert.Equal(1, onDropping); Assert.Equal(1, onDropped); HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
public async Task LocalOrchestrator_GetEstimatedChanges_BeforeInitialized_ShouldThrowError_IfScopeExistsAndIsEmpty() { var dbNameSrv = HelperDatabase.GetRandomName("tcp_lo_srv"); await HelperDatabase.CreateDatabaseAsync(ProviderType.Sql, dbNameSrv, true); var dbNameCli = HelperDatabase.GetRandomName("tcp_lo_cli"); await HelperDatabase.CreateDatabaseAsync(ProviderType.Sql, dbNameCli, true); var csServer = HelperDatabase.GetConnectionString(ProviderType.Sql, dbNameSrv); var serverProvider = new SqlSyncProvider(csServer); var csClient = HelperDatabase.GetConnectionString(ProviderType.Sql, dbNameCli); var clientProvider = new SqlSyncProvider(csClient); await new AdventureWorksContext((dbNameSrv, ProviderType.Sql, serverProvider), true, false).Database.EnsureCreatedAsync(); await new AdventureWorksContext((dbNameCli, ProviderType.Sql, clientProvider), true, false).Database.EnsureCreatedAsync(); var scopeName = "scopesnap1"; // Make a first sync to be sure everything is in place var agent = new SyncAgent(clientProvider, serverProvider); // Get the orchestrators var localOrchestrator = agent.LocalOrchestrator; // Client 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((dbNameCli, ProviderType.Sql, clientProvider))) { 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(); } // create the local scope, empty var scopeInfo = await localOrchestrator.GetClientScopeInfoAsync(scopeName); // Get changes to be populated to the server // Since we are new and not yet initialized, no rows are marked to be sent var ex = await Assert.ThrowsAsync <SyncException>(() => localOrchestrator.GetEstimatedChangesCountAsync(scopeName)); Assert.Equal("MissingLocalOrchestratorSchemaException", ex.TypeName); }
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); }
public async Task Table_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 options = new SyncOptions(); var setup = new SyncSetup(new string[] { "SalesLT.Product" }); var table = new SyncTable("Product", "SalesLT"); var colID = new SyncColumn("ID", typeof(Guid)); var colName = new SyncColumn("Name", typeof(string)); table.Columns.Add(colID); table.Columns.Add(colName); table.Columns.Add("Number", typeof(int)); table.PrimaryKeys.Add("ID"); var localOrchestrator = new LocalOrchestrator(sqlProvider, options, setup); var onCreating = false; var onCreated = false; localOrchestrator.OnTableCreating(ttca => { var addingID = Environment.NewLine + $"ALTER TABLE {ttca.TableName.Schema().Quoted()} ADD internal_id int identity(1,1)"; ttca.Command.CommandText += addingID; onCreating = true; }); localOrchestrator.OnTableCreated(ttca => { onCreated = true; }); var isCreated = await localOrchestrator.CreateTableAsync(table); Assert.True(isCreated); 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, "Product", "SalesLT").ConfigureAwait(false); Assert.Equal(4, cols.Rows.Count); Assert.NotNull(cols.Rows.FirstOrDefault(r => r["name"].ToString() == "internal_id")); c.Close(); } HelperDatabase.DropDatabase(ProviderType.Sql, dbName); }
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 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); }