/// <summary> /// Launch a simple sync, over TCP network, each sql server (client and server are reachable through TCP cp /// </summary> /// <returns></returns> private static async Task SynchronizeAsync() { // Create 2 Sql Sync providers var serverProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(serverDbName)); var clientProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientDbName)); // Tables involved in the sync process: var tables = allTables; // Creating an agent that will handle all the process var agent = new SyncAgent(clientProvider, serverProvider, tables); // Using the Progress pattern to handle progession during the synchronization var progress = new Progress <ProgressArgs>(s => Console.WriteLine($"[client]: {s.Context.SyncStage}:\t{s.Message}")); // Setting configuration options agent.SetConfiguration(s => { s.ScopeInfoTableName = "tscopeinfo"; s.SerializationFormat = Dotmim.Sync.Enumerations.SerializationFormat.Binary; s.StoredProceduresPrefix = "s"; s.StoredProceduresSuffix = ""; s.TrackingTablesPrefix = "t"; s.TrackingTablesSuffix = ""; }); agent.SetOptions(opt => { opt.BatchDirectory = Path.Combine(SyncOptions.GetDefaultUserBatchDiretory(), "sync"); opt.BatchSize = 100; opt.CleanMetadatas = true; opt.UseBulkOperations = true; opt.UseVerboseErrors = false; }); do { Console.Clear(); Console.WriteLine("Sync Start"); try { // Launch the sync process var s1 = await agent.SynchronizeAsync(progress); // Write results Console.WriteLine(s1); } catch (Exception e) { Console.WriteLine(e.Message); } //Console.WriteLine("Sync Ended. Press a key to start again, or Escapte to end"); } while (Console.ReadKey().Key != ConsoleKey.Escape); Console.WriteLine("End"); }
/// <summary> /// Launch a simple sync, over TCP network, each sql server (client and server are reachable through TCP cp /// </summary> /// <returns></returns> private static async Task SynchronizeExistingTablesAsync() { string serverName = "ServerTablesExist"; string clientName = "ClientsTablesExist"; await DbHelper.EnsureDatabasesAsync(serverName); await DbHelper.EnsureDatabasesAsync(clientName); // Create 2 Sql Sync providers var serverProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(serverName)); var clientProvider = new SqlSyncProvider(DbHelper.GetDatabaseConnectionString(clientName)); // Tables involved in the sync process: var tables = allTables; // Creating an agent that will handle all the process var agent = new SyncAgent(clientProvider, serverProvider, tables); // Using the Progress pattern to handle progession during the synchronization var progress = new Progress <ProgressArgs>(s => Console.WriteLine($"[client]: {s.Context.SyncStage}:\t{s.Message}")); // Setting configuration options agent.SetConfiguration(s => { s.ScopeInfoTableName = "tscopeinfo"; s.SerializationFormat = Dotmim.Sync.Enumerations.SerializationFormat.Binary; s.StoredProceduresPrefix = "s"; s.StoredProceduresSuffix = ""; s.TrackingTablesPrefix = "t"; s.TrackingTablesSuffix = ""; }); agent.SetOptions(opt => { opt.BatchDirectory = Path.Combine(SyncOptions.GetDefaultUserBatchDiretory(), "sync"); opt.BatchSize = 100; opt.CleanMetadatas = true; opt.UseBulkOperations = true; opt.UseVerboseErrors = false; }); var remoteProvider = agent.RemoteProvider as CoreProvider; var dpAction = new Action <DatabaseProvisionedArgs>(args => { Console.WriteLine($"-- [InterceptDatabaseProvisioned] -- "); var sql = $"Update tscopeinfo set scope_last_sync_timestamp = 0 where [scope_is_local] = 1"; var cmd = args.Connection.CreateCommand(); cmd.Transaction = args.Transaction; cmd.CommandText = sql; cmd.ExecuteNonQuery(); }); remoteProvider.InterceptDatabaseProvisioned(dpAction); agent.LocalProvider.InterceptDatabaseProvisioned(dpAction); do { Console.Clear(); Console.WriteLine("Sync Start"); try { // Launch the sync process var s1 = await agent.SynchronizeAsync(progress); // Write results Console.WriteLine(s1); } catch (Exception e) { Console.WriteLine(e.Message); } //Console.WriteLine("Sync Ended. Press a key to start again, or Escapte to end"); } while (Console.ReadKey().Key != ConsoleKey.Escape); Console.WriteLine("End"); }
internal SyncContext Sync(string value) { if (String.IsNullOrEmpty(value)) { throw new Exception("Loading a project requires a name. Ex : dotnet sync --load project01"); } Project project = DataStore.Current.LoadProject(value); if (project == null) { throw new Exception($"Project {value} does not exists."); } if (project.ServerProvider == null || string.IsNullOrEmpty(project.ServerProvider.ConnectionString)) { throw new Exception($"Server provider for project {project.Name} is not correctly defined. See help: dotnet sync provider --help"); } if (project.ClientProvider == null || string.IsNullOrEmpty(project.ClientProvider.ConnectionString)) { throw new Exception($"Client provider for project {project.Name} is not correctly defined. See help: dotnet sync provider --help"); } if (project.ServerProvider.ProviderType != ProviderType.Web && (project.Tables == null || project.Tables.Count <= 0)) { throw new Exception($"No table configured for project {project.Name}. See help: dotnet sync table --help"); } IRemoteOrchestrator remoteOrchestrator; ILocalOrchestrator localOrchestrator; switch (project.ServerProvider.ProviderType) { case ProviderType.Sqlite: throw new Exception("Can't use Sqlite as a server provider"); case ProviderType.Web: remoteOrchestrator = new WebClientOrchestrator(new Uri(project.ServerProvider.ConnectionString)); break; case ProviderType.MySql: remoteOrchestrator = new RemoteOrchestrator(new MySqlSyncProvider(project.ServerProvider.ConnectionString)); break; case ProviderType.SqlServer: default: remoteOrchestrator = new RemoteOrchestrator(new SqlSyncProvider(project.ServerProvider.ConnectionString)); break; } switch (project.ClientProvider.ProviderType) { case ProviderType.Web: throw new Exception("Web proxy is used as a proxy server. You have to use an ASP.NET web backend. CLI uses a proxy as server provider"); case ProviderType.Sqlite: localOrchestrator = new LocalOrchestrator(new SqliteSyncProvider(project.ClientProvider.ConnectionString)); break; case ProviderType.MySql: localOrchestrator = new LocalOrchestrator(new MySqlSyncProvider(project.ClientProvider.ConnectionString)); break; case ProviderType.SqlServer: default: localOrchestrator = new LocalOrchestrator(new SqlSyncProvider(project.ClientProvider.ConnectionString)); break; } SyncAgent agent = null; if (project.ServerProvider.ProviderType != ProviderType.Web) { agent = new SyncAgent(localOrchestrator, remoteOrchestrator); var syncSchema = new SyncSchema(); //var syncConfiguration = agent.LocalOrchestrator.Configuration; foreach (var t in project.Tables.OrderBy(tbl => tbl.Order)) { // Potentially user can pass something like [SalesLT].[Product] // or SalesLT.Product or Product. ParserName will handle it var parser = ParserName.Parse(t.Name); var tableName = parser.ObjectName; var schema = string.IsNullOrEmpty(t.Schema) ? parser.SchemaName : t.Schema; var dmTable = new DmTable(tableName); if (!String.IsNullOrEmpty(schema)) { dmTable.Schema = schema; } dmTable.SyncDirection = t.Direction; agent.SetSchema(agentSchema => agentSchema.Add(dmTable)); } agent.SetOptions(o => o.BatchDirectory = string.IsNullOrEmpty(project.Configuration.BatchDirectory) ? null : project.Configuration.BatchDirectory); agent.SetOptions(o => o.BatchSize = (int)Math.Min(Int32.MaxValue, project.Configuration.DownloadBatchSizeInKB)); //agent.SetOptions(o => o.SerializationFormat = project.Configuration.SerializationFormat); //agent.Options.UseBulkOperations = project.Configuration.UseBulkOperation; agent.SetSchema(agentSchema => { agentSchema.ConflictResolutionPolicy = project.Configuration.ConflictResolutionPolicy; }); } else { agent = new SyncAgent(localOrchestrator, remoteOrchestrator); } agent.LocalOrchestrator.OnTableChangesSelected(tcs => Console.WriteLine($"Changes selected for table {tcs.TableChangesSelected.TableName}: {tcs.TableChangesSelected.TotalChanges}")); agent.LocalOrchestrator.OnTableChangesApplied(tca => Console.WriteLine($"Changes applied for table {tca.TableChangesApplied.Table.TableName}: [{tca.TableChangesApplied.State}] {tca.TableChangesApplied.Applied}")); // synchronous call var syncContext = agent.SynchronizeAsync().GetAwaiter().GetResult(); var tsEnded = TimeSpan.FromTicks(syncContext.CompleteTime.Ticks); var tsStarted = TimeSpan.FromTicks(syncContext.StartTime.Ticks); var durationTs = tsEnded.Subtract(tsStarted); var durationstr = $"{durationTs.Hours}:{durationTs.Minutes}:{durationTs.Seconds}.{durationTs.Milliseconds}"; Console.ForegroundColor = ConsoleColor.Green; var s = $"Synchronization done. " + Environment.NewLine + $"\tTotal changes downloaded: {syncContext.TotalChangesDownloaded} " + Environment.NewLine + $"\tTotal changes uploaded: {syncContext.TotalChangesUploaded}" + Environment.NewLine + $"\tTotal duration :{durationstr} "; Console.WriteLine(s); Console.ResetColor(); return(syncContext); }