public async Task Kestrell_Server_Request_EnsureSuccess() { using (var server = new KestrellTestServer()) { var clientHandler = new ResponseDelegate(async baseAdress => { var httpClient = new HttpClient(); var response = await httpClient.GetAsync(baseAdress + "first"); response.EnsureSuccessStatusCode(); var resString = await response.Content.ReadAsStringAsync(); Assert.Equal("first_first", resString); }); var serverHandler = new RequestDelegate(async context => { var pathFirst = new PathString("/first"); Assert.Equal(context.Request.Path, pathFirst); await context.Response.WriteAsync("first_first"); }); await server.Run(serverHandler, clientHandler); }; }
public static async Task SyncHttpThroughKestellAsync() { // server provider var serverProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(serverDbName)); // client provider var client1Provider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientDbName)); // proxy client provider var proxyClientProvider = new WebProxyClientProvider(); var tables = new string[] { "ProductCategory", "ProductDescription", "ProductModel", "Product", "ProductModelProductDescription", "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" }; var configuration = new Action <SyncConfiguration>(conf => { conf.ScopeName = "AdventureWorks"; conf.ScopeInfoTableName = "tscopeinfo"; conf.SerializationFormat = Dotmim.Sync.Enumerations.SerializationFormat.Binary; conf.StoredProceduresPrefix = "s"; conf.StoredProceduresSuffix = ""; conf.TrackingTablesPrefix = "t"; conf.TrackingTablesSuffix = ""; conf.Add(tables); }); var optionsClient = new Action <SyncOptions>(opt => { opt.BatchDirectory = Path.Combine(SyncOptions.GetDefaultUserBatchDiretory(), "client"); opt.BatchSize = 100; opt.CleanMetadatas = true; opt.UseBulkOperations = true; opt.UseVerboseErrors = false; }); var optionsServer = new Action <SyncOptions>(opt => { opt.BatchDirectory = Path.Combine(SyncOptions.GetDefaultUserBatchDiretory(), "server"); opt.BatchSize = 100; opt.CleanMetadatas = true; opt.UseBulkOperations = true; opt.UseVerboseErrors = false; }); var serverHandler = new RequestDelegate(async context => { var proxyServerProvider = WebProxyServerProvider.Create(context, serverProvider, configuration, optionsServer); await proxyServerProvider.HandleRequestAsync(context); }); using (var server = new KestrellTestServer()) { var clientHandler = new ResponseDelegate(async(serviceUri) => { proxyClientProvider.ServiceUri = new Uri(serviceUri); var syncAgent = new SyncAgent(client1Provider, proxyClientProvider); do { Console.Clear(); Console.WriteLine("Sync Start"); try { var cts = new CancellationTokenSource(); Console.WriteLine("--------------------------------------------------"); Console.WriteLine("1 : Normal synchronization."); Console.WriteLine("2 : Synchronization with reinitialize"); Console.WriteLine("3 : Synchronization with upload and reinitialize"); Console.WriteLine("--------------------------------------------------"); Console.WriteLine("What's your choice ? "); Console.WriteLine("--------------------------------------------------"); var choice = Console.ReadLine(); if (int.TryParse(choice, out var choiceNumber)) { Console.WriteLine($"You choose {choice}. Start operation...."); switch (choiceNumber) { case 1: var s1 = await syncAgent.SynchronizeAsync(cts.Token); Console.WriteLine(s1); break; case 2: s1 = await syncAgent.SynchronizeAsync(SyncType.Reinitialize, cts.Token); Console.WriteLine(s1); break; case 3: s1 = await syncAgent.SynchronizeAsync(SyncType.ReinitializeWithUpload, cts.Token); Console.WriteLine(s1); break; default: break; } } } catch (SyncException e) { Console.WriteLine(e.ToString()); } catch (Exception e) { Console.WriteLine("UNKNOW EXCEPTION : " + e.Message); } Console.WriteLine("--------------------------------------------------"); Console.WriteLine("Press a key to choose again, or Escapte to end"); } while (Console.ReadKey().Key != ConsoleKey.Escape); }); await server.Run(serverHandler, clientHandler); } }
public async static Task SyncHttpThroughKestellAsync() { // server provider var serverProvider = new SqlSyncProvider(GetDatabaseConnectionString("AdventureWorks")); // proxy server based on server provider var proxyServerProvider = new WebProxyServerProvider(serverProvider); // client provider var client1Provider = new SqlSyncProvider(GetDatabaseConnectionString("Adv")); // proxy client provider var proxyClientProvider = new WebProxyClientProvider(); var tables = new string[] { "ProductCategory", "ProductDescription", "ProductModel", "Product", "ProductModelProductDescription", "Address", "Customer", "CustomerAddress", "SalesOrderHeader", "SalesOrderDetail" }; var configuration = new SyncConfiguration(tables) { ScopeName = "AdventureWorks", ScopeInfoTableName = "tscopeinfo", SerializationFormat = Dotmim.Sync.Enumerations.SerializationFormat.Binary, DownloadBatchSizeInKB = 400, StoredProceduresPrefix = "s", StoredProceduresSuffix = "", TrackingTablesPrefix = "t", TrackingTablesSuffix = "", }; var serverHandler = new RequestDelegate(async context => { proxyServerProvider.Configuration = configuration; await proxyServerProvider.HandleRequestAsync(context); }); using (var server = new KestrellTestServer()) { var clientHandler = new ResponseDelegate(async(serviceUri) => { proxyClientProvider.ServiceUri = new Uri(serviceUri); var syncAgent = new SyncAgent(client1Provider, proxyClientProvider); do { Console.Clear(); Console.WriteLine("Sync Start"); try { CancellationTokenSource cts = new CancellationTokenSource(); Console.WriteLine("--------------------------------------------------"); Console.WriteLine("1 : Normal synchronization."); Console.WriteLine("2 : Fill configuration from server side"); Console.WriteLine("3 : Synchronization with reinitialize"); Console.WriteLine("4 : Synchronization with upload and reinitialize"); Console.WriteLine("5 : Deprovision everything from client side (tables included)"); Console.WriteLine("6 : Deprovision everything from client side (tables not included)"); Console.WriteLine("7 : Deprovision everything from server side (tables not included)"); Console.WriteLine("8 : Provision everything on the client side (tables included)"); Console.WriteLine("9 : Provision everything on the server side (tables not included)"); Console.WriteLine("10 : Insert datas on client"); Console.WriteLine("--------------------------------------------------"); Console.WriteLine("What's your choice ? "); Console.WriteLine("--------------------------------------------------"); var choice = Console.ReadLine(); if (int.TryParse(choice, out int choiceNumber)) { Console.WriteLine($"You choose {choice}. Start operation...."); switch (choiceNumber) { case 1: var s1 = await syncAgent.SynchronizeAsync(cts.Token); Console.WriteLine(s1); break; case 2: SyncContext ctx = new SyncContext(Guid.NewGuid()); SqlSyncProvider syncConfigProvider = new SqlSyncProvider(GetDatabaseConnectionString("AdventureWorks")); (ctx, configuration.Schema) = await syncConfigProvider.EnsureSchemaAsync(ctx, new Dotmim.Sync.Messages.MessageEnsureSchema { Schema = configuration.Schema, SerializationFormat = Dotmim.Sync.Enumerations.SerializationFormat.Json }); break; case 3: s1 = await syncAgent.SynchronizeAsync(SyncType.Reinitialize, cts.Token); Console.WriteLine(s1); break; case 4: s1 = await syncAgent.SynchronizeAsync(SyncType.ReinitializeWithUpload, cts.Token); Console.WriteLine(s1); break; case 5: SqlSyncProvider clientSyncProvider = syncAgent.LocalProvider as SqlSyncProvider; await clientSyncProvider.DeprovisionAsync(configuration, SyncProvision.All | SyncProvision.Table); Console.WriteLine("Deprovision complete on client"); break; case 6: SqlSyncProvider client2SyncProvider = syncAgent.LocalProvider as SqlSyncProvider; await client2SyncProvider.DeprovisionAsync(configuration, SyncProvision.All); Console.WriteLine("Deprovision complete on client"); break; case 7: SqlSyncProvider remoteSyncProvider = new SqlSyncProvider(GetDatabaseConnectionString("AdventureWorks")); await remoteSyncProvider.DeprovisionAsync(configuration, SyncProvision.All); Console.WriteLine("Deprovision complete on remote"); break; case 8: SqlSyncProvider clientSyncProvider2 = syncAgent.LocalProvider as SqlSyncProvider; await clientSyncProvider2.ProvisionAsync(configuration, SyncProvision.All | SyncProvision.Table); Console.WriteLine("Provision complete on client"); break; case 9: SqlSyncProvider remoteSyncProvider2 = new SqlSyncProvider(GetDatabaseConnectionString("AdventureWorks")); await remoteSyncProvider2.ProvisionAsync(configuration, SyncProvision.All); Console.WriteLine("Provision complete on remote"); break; case 10: var c = GetDatabaseConnectionString("Adv"); var catId = await InsertProductCategory(c); var modelId = await InsertProductModel(c); await InsertProduct(c, catId, modelId); Console.WriteLine("Inserted a model, a category and a product."); break; default: break; } } } catch (SyncException e) { Console.WriteLine(e.ToString()); } catch (Exception e) { Console.WriteLine("UNKNOW EXCEPTION : " + e.Message); } Console.WriteLine("--------------------------------------------------"); Console.WriteLine("Press a key to choose again, or Escapte to end"); } while (Console.ReadKey().Key != ConsoleKey.Escape); }); await server.Run(serverHandler, clientHandler); } }
public static async Task SyncHttpThroughKestellAsync() { // server provider // Create 2 Sql Sync providers var serverProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(serverDbName)); var clientProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientDbName)); // ---------------------------------- // Client side // ---------------------------------- var clientOptions = new SyncOptions { BatchSize = 500 }; var proxyClientProvider = new WebClientOrchestrator(); // ---------------------------------- // Web Server side // ---------------------------------- var setup = new SyncSetup(allTables) { ScopeName = "all_tables_scope", StoredProceduresPrefix = "s", StoredProceduresSuffix = "", TrackingTablesPrefix = "t", TrackingTablesSuffix = "", TriggersPrefix = "", TriggersSuffix = "t" }; // snapshot directory var directory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Snapshots"); // ---------------------------------- // Create a snapshot // ---------------------------------- Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"Creating snapshot"); var remoteOrchestrator = new RemoteOrchestrator(serverProvider); await remoteOrchestrator.CreateSnapshotAsync(new SyncContext(), setup, directory, 500, CancellationToken.None); Console.WriteLine($"Done."); Console.ResetColor(); // ---------------------------------- // Insert a value after snapshot created // ---------------------------------- using (var c = serverProvider.CreateConnection()) { var command = c.CreateCommand(); command.CommandText = "INSERT INTO [dbo].[ProductCategory] ([Name]) VALUES ('Bikes revolution');"; c.Open(); command.ExecuteNonQuery(); c.Close(); } var webServerOptions = new WebServerOptions { SnapshotsDirectory = directory }; // Creating an agent that will handle all the process var agent = new SyncAgent(clientProvider, proxyClientProvider); agent.Options = clientOptions; var configureServices = new Action <IServiceCollection>(services => { services.AddSyncServer <SqlSyncProvider>(serverProvider.ConnectionString, setup, webServerOptions); }); var serverHandler = new RequestDelegate(async context => { var webProxyServer = context.RequestServices.GetService(typeof(WebProxyServerOrchestrator)) as WebProxyServerOrchestrator; await webProxyServer.HandleRequestAsync(context); }); using (var server = new KestrellTestServer(configureServices)) { var clientHandler = new ResponseDelegate(async(serviceUri) => { proxyClientProvider.ServiceUri = serviceUri; do { Console.Clear(); Console.WriteLine("Web sync start"); try { var progress = new SynchronousProgress <ProgressArgs>(pa => Console.WriteLine($"{pa.Context.SyncStage}\t {pa.Message}")); var s = await agent.SynchronizeAsync(progress); Console.WriteLine(s); } catch (SyncException e) { Console.WriteLine(e.ToString()); } catch (Exception e) { Console.WriteLine("UNKNOW EXCEPTION : " + e.Message); } Console.WriteLine("Sync Ended. Press a key to start again, or Escapte to end"); } while (Console.ReadKey().Key != ConsoleKey.Escape); }); await server.Run(serverHandler, clientHandler); } }
public async Task RemoteOrchestrator_HttpGetEstimatedChanges_WithFilters_ShouldReturnDeletedRowsCount() { 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, true).Database.EnsureCreatedAsync(); await new AdventureWorksContext((dbNameCli, ProviderType.Sql, clientProvider), true, false).Database.EnsureCreatedAsync(); var scopeName = "scopesnap1"; var setup = GetFilterSetup(); // Create a kestrell server var kestrell = new KestrellTestServer(false); // configure server orchestrator kestrell.AddSyncServer(serverProvider.GetType(), serverProvider.ConnectionString, scopeName, setup); var serviceUri = kestrell.Run(); var rowsCount = GetFilterServerDatabaseRowsCount((dbNameSrv, ProviderType.Sql, serverProvider)); var remoteOrchestrator = new WebRemoteOrchestrator(serviceUri); // Make a first sync to be sure everything is in place var agent = new SyncAgent(clientProvider, remoteOrchestrator); var parameters = new SyncParameters(("CustomerID", AdventureWorksContext.CustomerIdForFilter)); // Making a first sync, will initialize everything we need var r = await agent.SynchronizeAsync(scopeName, parameters); Assert.Equal(rowsCount, r.TotalChangesDownloaded); // Get the orchestrators var localOrchestrator = agent.LocalOrchestrator; Guid otherCustomerId; // Server side : Create a sales order header + 3 sales order details linked to the filter // and create 1 sales order header not linked to filter using var ctxServer = new AdventureWorksContext((dbNameSrv, ProviderType.Sql, serverProvider), true); // get another customer than the filter one otherCustomerId = ctxServer.Customer.First(c => c.CustomerId != AdventureWorksContext.CustomerIdForFilter).CustomerId; var soh = new SalesOrderHeader { SalesOrderNumber = $"SO-99999", RevisionNumber = 1, Status = 5, OnlineOrderFlag = true, PurchaseOrderNumber = "PO348186287", AccountNumber = "10-4020-000609", CustomerId = AdventureWorksContext.CustomerIdForFilter, ShipToAddressId = 4, BillToAddressId = 5, ShipMethod = "CAR TRANSPORTATION", SubTotal = 6530.35M, TaxAmt = 70.4279M, Freight = 22.0087M, TotalDue = 6530.35M + 70.4279M + 22.0087M }; var soh2 = new SalesOrderHeader { SalesOrderNumber = $"SO-99999", RevisionNumber = 1, Status = 5, OnlineOrderFlag = true, PurchaseOrderNumber = "PO348186287", AccountNumber = "10-4020-000609", CustomerId = otherCustomerId, ShipToAddressId = 4, BillToAddressId = 5, ShipMethod = "CAR TRANSPORTATION", SubTotal = 6530.35M, TaxAmt = 70.4279M, Freight = 22.0087M, TotalDue = 6530.35M + 70.4279M + 22.0087M }; var productId = ctxServer.Product.First().ProductId; var sod1 = new SalesOrderDetail { OrderQty = 1, ProductId = productId, UnitPrice = 3578.2700M }; var sod2 = new SalesOrderDetail { OrderQty = 2, ProductId = productId, UnitPrice = 44.5400M }; var sod3 = new SalesOrderDetail { OrderQty = 2, ProductId = productId, UnitPrice = 1431.5000M }; soh.SalesOrderDetail.Add(sod1); soh.SalesOrderDetail.Add(sod2); soh.SalesOrderDetail.Add(sod3); ctxServer.SalesOrderHeader.Add(soh); ctxServer.SalesOrderHeader.Add(soh2); await ctxServer.SaveChangesAsync(); // Making a second sync, with these new rows r = await agent.SynchronizeAsync(scopeName, parameters); Assert.Equal(4, r.TotalChangesDownloaded); // now delete these lines on server ctxServer.SalesOrderDetail.Remove(sod1); ctxServer.SalesOrderDetail.Remove(sod2); ctxServer.SalesOrderDetail.Remove(sod3); ctxServer.SalesOrderHeader.Remove(soh); await ctxServer.SaveChangesAsync(); // Get changes from server var clientScope = await localOrchestrator.GetClientScopeInfoAsync(scopeName); var changes = await remoteOrchestrator.GetEstimatedChangesCountAsync(clientScope, parameters); Assert.Null(changes.ServerBatchInfo); Assert.NotNull(changes.ServerChangesSelected); Assert.Equal(2, changes.ServerChangesSelected.TableChangesSelected.Count); Assert.Equal(4, changes.ServerChangesSelected.TableChangesSelected.Sum(tcs => tcs.Deletes)); Assert.Equal(0, changes.ServerChangesSelected.TableChangesSelected.Sum(tcs => tcs.Upserts)); Assert.Contains("SalesOrderDetail", changes.ServerChangesSelected.TableChangesSelected.Select(tcs => tcs.TableName).ToList()); Assert.Contains("SalesOrderHeader", changes.ServerChangesSelected.TableChangesSelected.Select(tcs => tcs.TableName).ToList()); }