public async Task ConflictUpdateUpdateClientWins(SyncConfiguration conf) { var id = Guid.NewGuid(); using (var sqlConnection = new SqliteConnection($"Data Source={fixture.ClientSqliteDb}")) { var script = $@"INSERT INTO ServiceTickets (ServiceTicketID, Title, Description, StatusValue, EscalationLevel, Opened, Closed, CustomerID) VALUES (@pk, 'Line for conflict', 'Description client', 1, 0, datetime('now'), NULL, 1)"; using (var sqlCmd = new SqliteCommand(script, sqlConnection)) { sqlCmd.Parameters.Add(new SqliteParameter("pk", id)); sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } agent.Configuration = conf; agent.Configuration.Add(fixture.Tables); var session = await agent.SynchronizeAsync(); //just check, even if it's not the real test :) // check statistics Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); Assert.Equal(0, session.TotalSyncConflicts); using (var sqlConnection = new SqliteConnection($"Data Source={fixture.ClientSqliteDb}")) { var script = $@"Update ServiceTickets Set Title = 'Updated from Client' Where ServiceTicketId = @pk"; using (var sqlCmd = new SqliteCommand(script, sqlConnection)) { sqlCmd.Parameters.Add(new SqliteParameter("pk", id)); sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var sqlConnection = new NpgsqlConnection(fixture.ServerConnectionString)) { var script = $@"Update ""ServiceTickets"" Set ""Title"" = 'Updated from Server' Where ""ServiceTicketID"" = '{id}'"; using (var sqlCmd = new NpgsqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } agent.ApplyChangedFailed += (s, args) => args.Action = ConflictAction.ClientWins; await Assert.RaisesAsync <ApplyChangeFailedEventArgs>( h => agent.ApplyChangedFailed += h, h => agent.ApplyChangedFailed -= h, async() => { session = await agent.SynchronizeAsync(); }); // check statistics Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); Assert.Equal(1, session.TotalSyncConflicts); string expectedRes = string.Empty; using (var sqlConnection = new NpgsqlConnection(fixture.ServerConnectionString)) { var script = $@"Select ""Title"" from ""ServiceTickets"" Where ""ServiceTicketID""='{id}'"; using (var sqlCmd = new NpgsqlCommand(script, sqlConnection)) { sqlConnection.Open(); expectedRes = sqlCmd.ExecuteScalar() as string; sqlConnection.Close(); } } // check good title on client Assert.Equal("Updated from Client", expectedRes); }
public async Task ConflictInsertInsertConfigurationClientWins(SyncConfiguration conf) { Guid id = Guid.NewGuid(); using (var sqlConnection = new SqliteConnection($"Data Source={fixture.ClientSqliteDb}")) { var script = $@"INSERT INTO ServiceTickets (ServiceTicketID, Title, Description, StatusValue, EscalationLevel, Opened, Closed, CustomerID) VALUES (@pk, 'Conflict Line Client', 'Description client', 1, 0, datetime('now'), NULL, 1)"; using (var sqlCmd = new SqliteCommand(script, sqlConnection)) { sqlCmd.Parameters.Add(new SqliteParameter("pk", id)); sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var sqlConnection = new NpgsqlConnection(fixture.ServerConnectionString)) { var script = $@"INSERT INTO ""ServiceTickets"" (""ServiceTicketID"", ""Title"", ""Description"", ""StatusValue"", ""EscalationLevel"", ""Opened"", ""Closed"", ""CustomerID"") VALUES ('{id.ToString()}', 'Conflict Line Server', 'Description client', 1, 0, now(), NULL, 1)"; using (var sqlCmd = new NpgsqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } agent.Configuration = conf; agent.Configuration.Add(fixture.Tables); agent.Configuration.ConflictResolutionPolicy = ConflictResolutionPolicy.ClientWins; var session = await agent.SynchronizeAsync(); // check statistics Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); Assert.Equal(1, session.TotalSyncConflicts); string expectedRes = string.Empty; using (var sqlConnection = new NpgsqlConnection(fixture.ServerConnectionString)) { var script = $@"Select ""Title"" from ""ServiceTickets"" Where ""ServiceTicketID""='{id.ToString()}'"; using (var sqlCmd = new NpgsqlCommand(script, sqlConnection)) { sqlConnection.Open(); expectedRes = sqlCmd.ExecuteScalar() as string; sqlConnection.Close(); } } // check good title on client Assert.Equal("Conflict Line Client", expectedRes); }
public SyncServiceConflictEventArgs(SyncConfiguration configuration, MetadataItem item, ItemStatus status) { Configuration = configuration; Item = item; NewStatus = status; }
public async Task ConflictInsertInsertConfigurationClientWins(SyncConfiguration conf) { Guid id = Guid.NewGuid(); using (var sqlConnection = new SqlConnection(fixture.Client1ConnectionString)) { var script = $@"INSERT [ServiceTickets] ([ServiceTicketID], [Title], [Description], [StatusValue], [EscalationLevel], [Opened], [Closed], [CustomerID]) VALUES (N'{id.ToString()}', N'Conflict Line Client', N'Description client', 1, 0, getdate(), NULL, 1)"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var sqlConnection = new SqlConnection(fixture.ServerConnectionString)) { var script = $@"INSERT [ServiceTickets] ([ServiceTicketID], [Title], [Description], [StatusValue], [EscalationLevel], [Opened], [Closed], [CustomerID]) VALUES (N'{id.ToString()}', N'Conflict Line Server', N'Description client', 1, 0, getdate(), NULL, 1)"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var server = new KestrellTestServer()) { var serverHandler = new RequestDelegate(async context => { conf.Tables = fixture.Tables; conf.ConflictResolutionPolicy = ConflictResolutionPolicy.ClientWins; serverProvider.SetConfiguration(conf); proxyServerProvider.SerializationFormat = conf.SerializationFormat; await proxyServerProvider.HandleRequestAsync(context); }); var clientHandler = new ResponseDelegate(async(serviceUri) => { proxyClientProvider.ServiceUri = new Uri(serviceUri); proxyClientProvider.SerializationFormat = conf.SerializationFormat; var session = await agent.SynchronizeAsync(); // check statistics Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); Assert.Equal(1, session.TotalSyncConflicts); }); await server.Run(serverHandler, clientHandler); } string expectedRes = string.Empty; using (var sqlConnection = new SqlConnection(fixture.ServerConnectionString)) { var script = $@"Select Title from [ServiceTickets] Where ServiceTicketID='{id.ToString()}'"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); expectedRes = sqlCmd.ExecuteScalar() as string; sqlConnection.Close(); } } // check good title on client Assert.Equal("Conflict Line Client", expectedRes); }
public async Task <ProviderRun> RunAsync(CoreProvider serverProvider, ProviderFixture <CoreProvider> serverFixture, string scopeName = null, string[] tables = null, SyncConfiguration conf = null, bool reuseAgent = true) { // server proxy var proxyServerProvider = new WebProxyServerProvider(serverProvider); var proxyClientProvider = new WebProxyClientProvider(); var syncTables = tables ?? serverFixture.Tables; // local test, through tcp if (this.NetworkType == NetworkType.Tcp) { // create agent if (this.Agent == null || !reuseAgent) { this.Agent = new SyncAgent(this.ClientProvider, serverProvider, syncTables); } // copy conf settings if (conf != null) { serverFixture.CopyConfiguration(this.Agent.Configuration, conf); } // Add Filers if (serverFixture.Filters != null && serverFixture.Filters.Count > 0) { serverFixture.Filters.ForEach(f => { if (!this.Agent.Configuration.Filters.Contains(f)) { this.Agent.Configuration.Filters.Add(f); } }); } // Add Filers values if (serverFixture.FilterParameters != null && serverFixture.FilterParameters.Count > 0) { foreach (var syncParam in serverFixture.FilterParameters) { if (!this.Agent.Parameters.Contains(syncParam)) { this.Agent.Parameters.Add(syncParam); } } } // sync try { this.BeginRun?.Invoke(this.Agent.RemoteProvider); this.Results = await this.Agent.SynchronizeAsync(); this.EndRun?.Invoke(this.Agent.RemoteProvider); } catch (Exception ex) { this.Exception = ex; Console.WriteLine(ex); } } // ----------------------------------------------------------------------- // HTTP // ----------------------------------------------------------------------- // tests through http proxy if (this.NetworkType == NetworkType.Http) { // client handler using (var server = new KestrellTestServer()) { // server handler var serverHandler = new RequestDelegate(async context => { var syncConfiguration = new SyncConfiguration(syncTables);// set proxy conf // copy conf settings if (conf != null) { serverFixture.CopyConfiguration(syncConfiguration, conf); } // set proxy conf proxyServerProvider.Configuration = syncConfiguration; // test if <> directory name works proxyServerProvider.Options = new SyncOptions(); proxyServerProvider.Options.BatchDirectory = Path.Combine(SyncOptions.GetDefaultUserBatchDiretory(), "server"); // Add Filers if (serverFixture.Filters != null && serverFixture.Filters.Count > 0) { serverFixture.Filters.ForEach(f => { if (!proxyServerProvider.Configuration.Filters.Contains(f)) { proxyServerProvider.Configuration.Filters.Add(f); } }); } // sync try { this.BeginRun?.Invoke(proxyServerProvider.LocalProvider); await proxyServerProvider.HandleRequestAsync(context); this.EndRun?.Invoke(proxyServerProvider.LocalProvider); } catch (Exception ew) { Console.WriteLine(ew); } }); var clientHandler = new ResponseDelegate(async(serviceUri) => { // create agent if (this.Agent == null || !reuseAgent) { this.Agent = new SyncAgent(this.ClientProvider, proxyClientProvider); } if (serverFixture.FilterParameters != null && serverFixture.FilterParameters.Count > 0) { foreach (var syncParam in serverFixture.FilterParameters) { if (!this.Agent.Parameters.Contains(syncParam)) { this.Agent.Parameters.Add(syncParam); } } } ((WebProxyClientProvider)this.Agent.RemoteProvider).ServiceUri = new Uri(serviceUri); try { this.Results = await this.Agent.SynchronizeAsync(); } catch (Exception ew) { this.Exception = ew; Console.WriteLine(ew); } }); await server.Run(serverHandler, clientHandler); } } return(this); }
public override IEnumerable <ADRawEntry> GetDataPage() { ExTraceGlobals.TenantRelocationTracer.TraceDebug((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration GetDataPage ..."); WatermarkMap watermarks = SyncConfiguration.GetReplicationCursors(base.RootOrgConfigurationSession); WatermarkMap configNcWatermarks = SyncConfiguration.GetReplicationCursors(base.RootOrgConfigurationSession, true, false); string dcName = base.RootOrgConfigurationSession.DomainController; ExTraceGlobals.TenantRelocationTracer.TraceDebug <string>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration dcName {0}", dcName); base.TenantConfigurationSession.DomainController = dcName; base.RecipientSession.DomainController = dcName; Guid watermarksInvocationId = base.RootOrgConfigurationSession.GetInvocationIdByFqdn(dcName); ExTraceGlobals.TenantRelocationTracer.TraceDebug <Guid>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration watermarksInvocationId {0}", watermarksInvocationId); long maxUsn = watermarks[watermarksInvocationId]; ExTraceGlobals.TenantRelocationTracer.TraceDebug <long>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration maxUsn {0}", maxUsn); this.PageToken.IsTenantConfigUnitInConfigNc = !ADSession.IsTenantConfigInDomainNC(base.RecipientSession.SessionSettings.GetAccountOrResourceForestFqdn()); if (this.PageToken.InvocationId == Guid.Empty) { this.PageToken.SetInvocationId(watermarksInvocationId, dcName); ExTraceGlobals.TenantRelocationTracer.TraceDebug <Guid>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration set this.PageToken.InvocationId to {0}", this.PageToken.InvocationId); } this.moreDataForThisPage = true; while (this.ShouldReadMoreData()) { ExTraceGlobals.TenantRelocationTracer.TraceDebug <string>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration this.PageToken.State = {0}", this.PageToken.State.ToString()); switch (this.PageToken.State) { case TenantRelocationSyncState.PreSyncAllObjects: if (this.PageToken.PreSyncLdapPagingCookie == null) { this.PageToken.PendingConfigNcWatermarks = configNcWatermarks; this.PageToken.PendingWatermarks = watermarks; this.PageToken.PendingWatermarksInvocationId = watermarksInvocationId; ExTraceGlobals.TenantRelocationTracer.TraceDebug <Guid>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration set this.PageToken.PendingWatermarksInvocationId to {0}", this.PageToken.PendingWatermarksInvocationId); } foreach (ADRawEntry entry in this.PreSyncAllObjects()) { ExTraceGlobals.TenantRelocationTracer.TraceDebug <ADObjectId>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration PreSyncAllObjects yield {0}", entry.Id); yield return(entry); } break; case TenantRelocationSyncState.EnumerateConfigUnitLiveObjects: foreach (ADRawEntry entry2 in this.ReadLiveObjects(maxUsn)) { ExTraceGlobals.TenantRelocationTracer.TraceDebug <ADObjectId>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration EnumerateConfigUnitLiveObjects yield {0}", entry2.Id); yield return(entry2); } this.PageToken.PendingWatermarksInvocationId = watermarksInvocationId; ExTraceGlobals.TenantRelocationTracer.TraceDebug <Guid>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration set this.PageToken.PendingWatermarksInvocationId to {0}", this.PageToken.PendingWatermarksInvocationId); if (this.PageToken.IsTenantConfigUnitInConfigNc) { this.PageToken.PendingConfigNcWatermarks = configNcWatermarks; } else { this.PageToken.PendingWatermarks = watermarks; } break; case TenantRelocationSyncState.EnumerateConfigUnitLinksInPage: ExTraceGlobals.TenantRelocationTracer.TraceDebug((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration EnumerateConfigUnitLinksInPage skips"); this.PageToken.SwitchToEnumerateLiveObjectsState(); break; case TenantRelocationSyncState.EnumerateOrganizationalUnitLiveObjects: foreach (ADRawEntry entry3 in this.ReadLiveObjects(maxUsn)) { ExTraceGlobals.TenantRelocationTracer.TraceDebug <ADObjectId>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration EnumerateOrganizationalUnitLiveObjects yield {0}", entry3.Id); yield return(entry3); } if (this.PageToken.IsTenantConfigUnitInConfigNc) { this.PageToken.PendingWatermarksInvocationId = watermarksInvocationId; ExTraceGlobals.TenantRelocationTracer.TraceDebug <Guid>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration set this.PageToken.PendingWatermarksInvocationId to {0}", this.PageToken.PendingWatermarksInvocationId); this.PageToken.PendingWatermarks = watermarks; } break; case TenantRelocationSyncState.EnumerateOrganizationalUnitLinksInPage: ExTraceGlobals.TenantRelocationTracer.TraceDebug((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration EnumerateConfigUnitLinksInPage skips"); this.PageToken.SwitchToEnumerateLiveObjectsState(); break; case TenantRelocationSyncState.EnumerateConfigUnitDeletedObjects: foreach (ADRawEntry entry4 in this.ReadDeletedObjects()) { ExTraceGlobals.TenantRelocationTracer.TraceDebug <ADObjectId>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration EnumerateConfigUnitDeletedObjects yield {0}", entry4.Id); yield return(entry4); } break; case TenantRelocationSyncState.EnumerateOrganizationalUnitDeletedObjects: if (!this.PageToken.IsTenantConfigUnitInConfigNc) { this.PageToken.SwitchToNextState(); } else { foreach (ADRawEntry entry5 in this.ReadDeletedObjects()) { ExTraceGlobals.TenantRelocationTracer.TraceDebug <ADObjectId>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration EnumerateOrganizationalUnitDeletedObjects yield {0}", entry5.Id); yield return(entry5); } } break; case TenantRelocationSyncState.EnumerateSpecialObjects: foreach (ADRawEntry entry6 in this.ReadSpecialObjects()) { ExTraceGlobals.TenantRelocationTracer.TraceDebug <ADObjectId>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration EnumerateSpecialObjects yield {0}", entry6.Id); yield return(entry6); } if (!this.PageToken.IsTenantConfigUnitInConfigNc) { this.PageToken.PendingWatermarksInvocationId = watermarksInvocationId; ExTraceGlobals.TenantRelocationTracer.TraceDebug <Guid>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration set this.PageToken.PendingWatermarksInvocationId to {0}", this.PageToken.PendingWatermarksInvocationId); this.PageToken.PendingConfigNcWatermarks = configNcWatermarks; } this.PageToken.SwitchToNextState(); break; default: ExTraceGlobals.TenantRelocationTracer.TraceError <string>((long)SyncConfiguration.TraceId, "Invalid PageToken stat {0}", this.PageToken.State.ToString()); throw new ArgumentException(this.PageToken.State.ToString()); } } ExTraceGlobals.TenantRelocationTracer.TraceDebug <long>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration this.PageToken.OrganizationalUnitObjectUSN = {0}", this.PageToken.OrganizationalUnitObjectUSN); if (this.PageToken.OrganizationalUnitObjectUSN > maxUsn + 1L) { this.PageToken.OrganizationalUnitObjectUSN = maxUsn + 1L; ExTraceGlobals.TenantRelocationTracer.TraceDebug <long>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration set this.PageToken.OrganizationalUnitObjectUSN to {0}", this.PageToken.OrganizationalUnitObjectUSN); } ExTraceGlobals.TenantRelocationTracer.TraceDebug <long>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration this.PageToken.OrganizationalUnitTombstoneUSN = {0}", this.PageToken.OrganizationalUnitTombstoneUSN); if (this.PageToken.OrganizationalUnitTombstoneUSN > maxUsn + 1L) { this.PageToken.OrganizationalUnitTombstoneUSN = maxUsn + 1L; ExTraceGlobals.TenantRelocationTracer.TraceDebug <long>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration set this.PageToken.OrganizationalUnitTombstoneUSN to {0}", this.PageToken.OrganizationalUnitTombstoneUSN); } ExTraceGlobals.TenantRelocationTracer.TraceDebug <long>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration this.PageToken.ConfigUnitObjectUSN = {0}", this.PageToken.ConfigUnitObjectUSN); if (this.PageToken.ConfigUnitObjectUSN > maxUsn + 1L) { this.PageToken.ConfigUnitObjectUSN = maxUsn + 1L; ExTraceGlobals.TenantRelocationTracer.TraceDebug <long>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration this.PageToken.ConfigUnitObjectUSN = {0}", this.PageToken.ConfigUnitObjectUSN); } ExTraceGlobals.TenantRelocationTracer.TraceDebug <long>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration this.PageToken.ConfigUnitTombstoneUSN = {0}", this.PageToken.ConfigUnitTombstoneUSN); if (this.PageToken.ConfigUnitTombstoneUSN > maxUsn + 1L) { this.PageToken.ConfigUnitTombstoneUSN = maxUsn + 1L; ExTraceGlobals.TenantRelocationTracer.TraceDebug <long>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration this.PageToken.ConfigUnitTombstoneUSN = {0}", this.PageToken.ConfigUnitTombstoneUSN); } ExTraceGlobals.TenantRelocationTracer.TraceDebug <long>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration this.PageToken.SpecialObjectsUSN = {0}", this.PageToken.SpecialObjectsUSN); if (this.PageToken.SpecialObjectsUSN > maxUsn + 1L) { this.PageToken.SpecialObjectsUSN = maxUsn + 1L; ExTraceGlobals.TenantRelocationTracer.TraceDebug <long>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration this.PageToken.SpecialObjectsUSN = {0}", this.PageToken.SpecialObjectsUSN); } this.PageToken.LastReadFailureStartTime = DateTime.MinValue; ExTraceGlobals.TenantRelocationTracer.TraceDebug <DateTime>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration set this.PageToken.LastReadFailureStartTime to {0}", this.PageToken.LastReadFailureStartTime); this.PageToken.Timestamp = DateTime.UtcNow; ExTraceGlobals.TenantRelocationTracer.TraceDebug <DateTime>((long)SyncConfiguration.TraceId, "TenantRelocationSyncConfiguration set this.PageToken.Timestamp to {0}", this.PageToken.Timestamp); yield break; }
public async Task ConflictInsertInsertConfigurationClientWins(SyncConfiguration conf) { Guid id = Guid.NewGuid(); using (var sqlConnection = new SqliteConnection(fixture.ClientSqliteConnectionString)) { var script = $@"INSERT INTO [ServiceTickets] ([ServiceTicketID], [Title], [Description], [StatusValue], [EscalationLevel], [Opened], [Closed], [CustomerID]) VALUES (@id, 'Conflict Line Client', 'Description client', 1, 0, datetime('now'), NULL, 1)"; using (var sqlCmd = new SqliteCommand(script, sqlConnection)) { sqlCmd.Parameters.AddWithValue("@id", id); sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var sqlConnection = new SqlConnection(fixture.ServerConnectionString)) { var script = $@"INSERT [ServiceTickets] ([ServiceTicketID], [Title], [Description], [StatusValue], [EscalationLevel], [Opened], [Closed], [CustomerID]) VALUES ('{id.ToString()}', 'Conflict Line Server', 'Description client', 1, 0, getdate(), NULL, 1)"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } agent.Configuration.DownloadBatchSizeInKB = conf.DownloadBatchSizeInKB; agent.Configuration.UseBulkOperations = conf.UseBulkOperations; agent.Configuration.SerializationFormat = conf.SerializationFormat; agent.Configuration.Add(fixture.Tables); agent.Configuration.ConflictResolutionPolicy = ConflictResolutionPolicy.ClientWins; var session = await agent.SynchronizeAsync(); // check statistics Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); Assert.Equal(1, session.TotalSyncConflicts); string expectedRes = string.Empty; using (var sqlConnection = new SqlConnection(fixture.ServerConnectionString)) { var script = $@"Select Title from [ServiceTickets] Where ServiceTicketID='{id.ToString()}'"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); expectedRes = sqlCmd.ExecuteScalar() as string; sqlConnection.Close(); } } // check good title on client Assert.Equal("Conflict Line Client", expectedRes); }
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"); } IProvider serverProvider, clientprovider; switch (project.ServerProvider.ProviderType) { case ProviderType.Sqlite: throw new Exception("Can't use Sqlite as a server provider"); case ProviderType.Web: serverProvider = new WebProxyClientProvider(new Uri(project.ServerProvider.ConnectionString)); break; case ProviderType.MySql: serverProvider = new MySqlSyncProvider(project.ServerProvider.ConnectionString); break; case ProviderType.SqlServer: default: serverProvider = 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: clientprovider = new SqliteSyncProvider(project.ClientProvider.ConnectionString); break; case ProviderType.MySql: clientprovider = new MySqlSyncProvider(project.ClientProvider.ConnectionString); break; case ProviderType.SqlServer: default: clientprovider = new SqlSyncProvider(project.ClientProvider.ConnectionString); break; } SyncAgent agent = null; if (project.ServerProvider.ProviderType != ProviderType.Web) { agent = new SyncAgent(clientprovider, serverProvider); SyncConfiguration syncConfiguration = agent.Configuration; foreach (var t in project.Tables.OrderBy(tbl => tbl.Order)) { // Potentially user can pass something like [SalesLT].[Product] // or SalesLT.Product or Product. ObjectNameParser will handle it ObjectNameParser parser = new ObjectNameParser(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; syncConfiguration.Add(dmTable); } syncConfiguration.BatchDirectory = string.IsNullOrEmpty(project.Configuration.BatchDirectory) ? null : project.Configuration.BatchDirectory; syncConfiguration.SerializationFormat = project.Configuration.SerializationFormat; syncConfiguration.UseBulkOperations = project.Configuration.UseBulkOperations; syncConfiguration.DownloadBatchSizeInKB = (int)Math.Min(Int32.MaxValue, project.Configuration.DownloadBatchSizeInKB); syncConfiguration.ConflictResolutionPolicy = project.Configuration.ConflictResolutionPolicy; } else { agent = new SyncAgent(clientprovider, serverProvider); } agent.TableChangesSelected += (sender, a) => Console.WriteLine($"Changes selected for table {a.TableChangesSelected.TableName}: {a.TableChangesSelected.TotalChanges}"); agent.TableChangesApplied += (sender, a) => Console.WriteLine($"Changes applied for table {a.TableChangesApplied.TableName}: [{a.TableChangesApplied.State}] {a.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); }
private static void Main(string[] args) { using (SqlConnection conn = new SqlConnection("Data Source=(local);Initial Catalog=sarasa;User Id=sa;Password=1234;Connect Timeout=120")) { SqlCommand cmd = new SqlCommand(@" SELECT * FROM notes WHERE note.language = 'es'" , conn); List <SyncArrayConfiguration> arrayConfig = new List <SyncArrayConfiguration>() { new SyncArrayConfiguration { SqlCommand = new SqlCommand(@" SELECT id_object AS '_id', id, description, languageId FROM dbo.Tags WHERE languageId = 'es'" , conn), AttributeName = "tags" }, new SyncArrayConfiguration { SqlCommand = new SqlCommand(@" SELECT id_object AS '_id', id, description, xmlData, languageId FROM dbo.Categories WHERE languageId = 'es'" , conn), AttributeName = "categories", XmlFields = new string[] { "xmlData" } } }; SyncDeleteConfiguration deleteCmd = new SyncDeleteConfiguration { SqlCommand = new SqlCommand(@" SELECT id_object AS '_id', createdOn FROM dbo.DeleteLog WHERE id_language = 'es'" , conn), ColumnsToCompareWithLastSyncDate = new string[] { "[createdOn]" }, }; var nodes = new Uri[] { new Uri("http://localhost:9200"), new Uri("http://localhost:9201") }; var connectionPool = new SniffingConnectionPool(nodes); var esConfig = new ConnectionConfiguration(connectionPool).UsePrettyResponses(); var syncConfig = new SyncConfiguration() { SqlConnection = conn, SqlCommand = cmd, ArraysConfiguration = arrayConfig, ColumnsToCompareWithLastSyncDate = new string[] { "[lastupdate]" }, DeleteConfiguration = deleteCmd, ElasticSearchConfiguration = esConfig, BulkSize = 500, _Index = new Index("sarasa"), _Type = "notes" }; var sync = new Sync(syncConfig); try { var response = sync.Exec(); if (response.BulkResponses.Any()) { foreach (var bulkResponse in response.BulkResponses) { Console.WriteLine("success: " + bulkResponse.Success); Console.WriteLine("http status code: " + bulkResponse.HttpStatusCode); Console.WriteLine("affected documents: " + bulkResponse.AffectedDocuments); Console.WriteLine("started on: " + bulkResponse.StartedOn); Console.WriteLine("bulk duration: " + bulkResponse.Duration + "ms"); if (!response.Success) { Console.WriteLine("es original exception: " + bulkResponse.ESexception); } Console.WriteLine("\n"); } Console.WriteLine("\nbulk avg duration: " + response.BulkResponses.Average(x => x.Duration) + "ms"); Console.WriteLine("\n"); } } catch (Exception ex) { Console.WriteLine("an error has occurred: " + ex.Message); } finally { Console.WriteLine("Execution has completed. Press any key to continue..."); Console.ReadKey(); } } }
public async Task ConflictUpdateUpdateClientWins(SyncConfiguration conf) { var id = Guid.NewGuid().ToString(); using (var sqlConnection = new SqliteConnection(fixture.ClientSqliteConnectionString)) { var script = $@"INSERT INTO [ServiceTickets] ([ServiceTicketID], [Title], [Description], [StatusValue], [EscalationLevel], [Opened], [Closed], [CustomerID]) VALUES (@id, 'Line for conflict', 'Description client', 1, 0, datetime('now'), NULL, 1)"; using (var sqlCmd = new SqliteCommand(script, sqlConnection)) { sqlCmd.Parameters.AddWithValue("@id", id); sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } agent.Configuration.DownloadBatchSizeInKB = conf.DownloadBatchSizeInKB; agent.Configuration.UseBulkOperations = conf.UseBulkOperations; agent.Configuration.SerializationFormat = conf.SerializationFormat; agent.Configuration.Add(fixture.Tables); var session = await agent.SynchronizeAsync(); //just check, even if it's not the real test :) // check statistics Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); Assert.Equal(0, session.TotalSyncConflicts); using (var sqlConnection = new SqliteConnection(fixture.ClientSqliteConnectionString)) { var script = $@"Update [ServiceTickets] Set Title = 'Updated from Client' Where ServiceTicketId = @id"; using (var sqlCmd = new SqliteCommand(script, sqlConnection)) { sqlCmd.Parameters.AddWithValue("@id", id); sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var sqlConnection = new SqlConnection(fixture.ServerConnectionString)) { var script = $@"Update [ServiceTickets] Set Title = 'Updated from Server' Where ServiceTicketId = '{id}'"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } agent.ApplyChangedFailed += (s, args) => args.Action = ConflictAction.ClientWins; await Assert.RaisesAsync <ApplyChangeFailedEventArgs>( h => agent.ApplyChangedFailed += h, h => agent.ApplyChangedFailed -= h, async() => { session = await agent.SynchronizeAsync(); }); // check statistics Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); Assert.Equal(1, session.TotalSyncConflicts); string expectedRes = string.Empty; using (var sqlConnection = new SqlConnection(fixture.ServerConnectionString)) { var script = $@"Select Title from [ServiceTickets] Where ServiceTicketID='{id}'"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); expectedRes = sqlCmd.ExecuteScalar() as string; sqlConnection.Close(); } } // check good title on client Assert.Equal("Updated from Client", expectedRes); }
public async Task UpdateFromClient(SyncConfiguration conf) { Guid newId = Guid.NewGuid(); var insertRowScript = $@"INSERT INTO [ServiceTickets] ([ServiceTicketID], [Title], [Description], [StatusValue], [EscalationLevel], [Opened], [Closed], [CustomerID]) VALUES ('{newId.ToString()}', 'Insert One Row in SQLite client', 'Description Insert One Row', 1, 0, datetime('now'), NULL, 1)"; using (var sqlConnection = new SQLiteConnection(fixture.ClientSQLiteConnectionString)) { using (var sqlCmd = new SQLiteCommand(insertRowScript, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var server = new KestrellTestServer()) { var serverHandler = new RequestDelegate(async context => { conf.Tables = fixture.Tables; serverProvider.SetConfiguration(conf); proxyServerProvider.SerializationFormat = conf.SerializationFormat; await proxyServerProvider.HandleRequestAsync(context); }); var clientHandler = new ResponseDelegate(async(serviceUri) => { proxyClientProvider.ServiceUri = new Uri(serviceUri); proxyClientProvider.SerializationFormat = conf.SerializationFormat; var session = await agent.SynchronizeAsync(); Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); }); await server.Run(serverHandler, clientHandler); } var updateRowScript = $@" Update [ServiceTickets] Set [Title] = 'Updated from SQLite Client side !' Where ServiceTicketId = '{newId.ToString()}'"; using (var sqlConnection = new SQLiteConnection(fixture.ClientSQLiteConnectionString)) { using (var sqlCmd = new SQLiteCommand(updateRowScript, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var server = new KestrellTestServer()) { var serverHandler = new RequestDelegate(async context => { conf.Tables = fixture.Tables; serverProvider.SetConfiguration(conf); proxyServerProvider.SerializationFormat = conf.SerializationFormat; await proxyServerProvider.HandleRequestAsync(context); }); var clientHandler = new ResponseDelegate(async(serviceUri) => { proxyClientProvider.ServiceUri = new Uri(serviceUri); proxyClientProvider.SerializationFormat = conf.SerializationFormat; var session = await agent.SynchronizeAsync(); Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); }); await server.Run(serverHandler, clientHandler); } }
private bool CheckReplicationStatus(ITopologyConfigurationSession session, WatermarkMap finishWaterMark, bool useConfigNC) { WatermarkMap replicationCursors = SyncConfiguration.GetReplicationCursors(session, useConfigNC, false); return(replicationCursors.ContainsAllChanges(finishWaterMark)); }
public CustomSyncEngine(DatabaseService databaseService, SyncConfiguration syncConfiguration) : base(syncConfiguration) { this.databaseService = databaseService; customContractResolvers = new Dictionary <Type, CustomContractResolver>(); }
public async Task InsertUpdateDeleteFromServer(SyncConfiguration conf) { Guid insertedId = Guid.NewGuid(); Guid updatedId = Guid.NewGuid(); Guid deletedId = Guid.NewGuid(); var script = $@"INSERT INTO ""ServiceTickets"" (""ServiceTicketID"", ""Title"", ""Description"", ""StatusValue"", ""EscalationLevel"", ""Opened"", ""Closed"", ""CustomerID"") VALUES ('{updatedId.ToString()}', 'Updated', 'Description', 1, 0, now(), NULL, 1); INSERT INTO ""ServiceTickets""(""ServiceTicketID"", ""Title"", ""Description"", ""StatusValue"", ""EscalationLevel"", ""Opened"", ""Closed"", ""CustomerID"") VALUES('{deletedId.ToString()}', 'Deleted', 'Description', 1, 0, now(), NULL, 1)"; using (var sqlConnection = new NpgsqlConnection(fixture.ServerConnectionString)) { using (var sqlCmd = new NpgsqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } agent.Configuration = conf; agent.Configuration.Add(fixture.Tables); var session = await agent.SynchronizeAsync(); Assert.Equal(2, session.TotalChangesDownloaded); Assert.Equal(0, session.TotalChangesUploaded); script = $@"INSERT INTO ""ServiceTickets"" (""ServiceTicketID"", ""Title"", ""Description"", ""StatusValue"", ""EscalationLevel"", ""Opened"", ""Closed"", ""CustomerID"") VALUES ('{insertedId.ToString()}', 'Inserted', 'Description', 1, 0, now(), NULL, 1); DELETE FROM ""ServiceTickets"" WHERE ""ServiceTicketID"" = '{deletedId.ToString()}'; UPDATE ""ServiceTickets"" set ""Description"" = 'Updated again' WHERE ""ServiceTicketID"" = '{updatedId.ToString()}';"; using (var sqlConnection = new NpgsqlConnection(fixture.ServerConnectionString)) { using (var sqlCmd = new NpgsqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } int insertApplied = 0; int updateApplied = 0; int deleteApplied = 0; agent.TableChangesApplied += (sender, args) => { switch (args.TableChangesApplied.State) { case Data.DmRowState.Added: insertApplied += args.TableChangesApplied.Applied; break; case Data.DmRowState.Modified: updateApplied += args.TableChangesApplied.Applied; break; case Data.DmRowState.Deleted: deleteApplied += args.TableChangesApplied.Applied; break; } }; session = await agent.SynchronizeAsync(); Assert.Equal(3, session.TotalChangesDownloaded); Assert.Equal(1, insertApplied); Assert.Equal(1, updateApplied); Assert.Equal(1, deleteApplied); Assert.Equal(0, session.TotalChangesUploaded); }
public CustomSyncEngine(DatabaseContext databaseContext, SyncConfiguration syncConfiguration) : base(syncConfiguration) { this.databaseContext = databaseContext; customContractResolvers = new Dictionary <Type, CustomContractResolver>(); }
public async Task <(SyncContext, SyncConfiguration)> EnsureConfigurationAsync(SyncContext context, SyncConfiguration configuration = null) { HttpMessage httpMessage = new HttpMessage(); httpMessage.SyncContext = context; httpMessage.Step = HttpStep.EnsureConfiguration; //Post request and get response var httpMessageResponse = await this.httpRequestHandler.ProcessRequest(httpMessage, cancellationToken); if (httpMessageResponse == null) { throw new Exception("Can't have an empty body"); } if (httpMessageResponse.EnsureConfiguration == null || httpMessageResponse.EnsureConfiguration.Configuration == null || httpMessageResponse.EnsureConfiguration.ConfigurationSet == null || httpMessageResponse.EnsureConfiguration.ConfigurationSet.Tables.Count <= 0) { throw new ArgumentException("Configuration can't be null"); } // get config & deserialize set var conf = httpMessageResponse.EnsureConfiguration.Configuration; var set = httpMessageResponse.EnsureConfiguration.ConfigurationSet.ConvertToDmSet(); httpMessageResponse.EnsureConfiguration.ConfigurationSet.Clear(); httpMessageResponse.EnsureConfiguration.ConfigurationSet.Dispose(); httpMessageResponse.EnsureConfiguration.ConfigurationSet = null; conf.ScopeSet = set; // get context var syncContext = httpMessageResponse.SyncContext; // because we need it after this.syncConfiguration = conf; return(syncContext, conf); }
public async System.Threading.Tasks.Task Setup() { // :code-block-start: initialize-realm app = App.Create(myRealmAppId); // :code-block-end: user = app.LogInAsync(Credentials.EmailPassword("*****@*****.**", "foobar")).Result; // :code-block-start: open-synced-realm config = new SyncConfiguration("myPart", user); //:hide-start: config.ObjectClasses = new[] { typeof(Task), typeof(MyClass), typeof(dotnet.User), typeof(CustomGetterSetter) }; Realm realm; //:hide-end: try { realm = await Realm.GetInstanceAsync(config); } catch (RealmFileAccessErrorException ex) { Console.WriteLine($@"Error creating or opening the realm file. {ex.Message}"); } //:hide-start: realm = await Realm.GetInstanceAsync(config); realm.Write(() => { realm.RemoveAll <Task>(); }); //:hide-end: // :code-block-end: // :code-block-start: open-synced-realm-sync var synchronousRealm = await Realm.GetInstanceAsync(config); // :code-block-end: // :code-block-start: create var testTask = new Task { Name = "Do this thing", Status = TaskStatus.Open.ToString(), Partition = "myPart" }; realm.Write(() => { realm.Add(testTask); }); // :code-block-end: testTaskId = testTask.Id; /* var schemas = config.ObjectClasses; * foreach (var schema in schemas) * { * Console.WriteLine(schema.FullName); * }*/ return; }
public async Task Setup() { app = App.Create(myRealmAppId); user = app.LogInAsync(Credentials.EmailPassword("*****@*****.**", "foobar")).Result; config = new SyncConfiguration("myPart", user); mongoClient = user.GetMongoClient("mongodb-atlas"); dbPlantInventory = mongoClient.GetDatabase("inventory"); plantsCollection = dbPlantInventory.GetCollection <Plant>("plants"); venus = new Plant { Name = "Venus Flytrap", Sunlight = Sunlight.Full, Color = PlantColor.White, Type = PlantType.Perennial, Partition = "Store 42" }; sweetBasil = new Plant { Name = "Sweet Basil", Sunlight = Sunlight.Partial, Color = PlantColor.Green, Type = PlantType.Annual, Partition = "Store 42" }; thaiBasil = new Plant { Name = "Thai Basil", Sunlight = Sunlight.Partial, Color = PlantColor.Green, Type = PlantType.Perennial, Partition = "Store 42" }; helianthus = new Plant { Name = "Helianthus", Sunlight = Sunlight.Full, Color = PlantColor.Yellow, Type = PlantType.Annual, Partition = "Store 42" }; petunia = new Plant { Name = "Petunia", Sunlight = Sunlight.Full, Color = PlantColor.Purple, Type = PlantType.Annual, Partition = "Store 47" }; var listofPlants = new List <Plant> { venus, sweetBasil, thaiBasil, helianthus, petunia }; var insertResult = await plantsCollection.InsertManyAsync(listofPlants); return; }
private static async Task TestSyncSQLite() { // Get SQL Server connection string ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); configurationBuilder.AddJsonFile("config.json", true); IConfiguration Configuration = configurationBuilder.Build(); var serverConfig = Configuration["AppConfiguration:ServerConnectionString"]; var clientConfig = Configuration["AppConfiguration:ClientSQLiteConnectionString"]; SqlSyncProvider serverProvider = new SqlSyncProvider(serverConfig); SQLiteSyncProvider clientProvider = new SQLiteSyncProvider(clientConfig); // With a config when we are in local mode (no proxy) SyncConfiguration configuration = new SyncConfiguration(new string[] { "Customers", "ServiceTickets" }); SyncAgent agent = new SyncAgent(clientProvider, serverProvider, configuration); agent.SyncProgress += SyncProgress; //(s,e) => //{ // switch (e.Context.SyncStage) // { // case SyncStage.EnsureConfiguration: // break; // case SyncStage.EnsureDatabase: // if (e.DatabaseScript != null) // e.Action = ChangeApplicationAction.Rollback; // break; // case SyncStage.SelectedChanges: // Console.WriteLine($"Selected changes : {e.ChangesStatistics.TotalSelectedChanges}. I:{e.ChangesStatistics.TotalSelectedChangesInserts}. U:{e.ChangesStatistics.TotalSelectedChangesUpdates}. D:{e.ChangesStatistics.TotalSelectedChangesDeletes}"); // break; // case SyncStage.ApplyingChanges: // Console.WriteLine($"Going to apply changes."); // e.Action = ChangeApplicationAction.Continue; // break; // case SyncStage.AppliedChanges: // Console.WriteLine($"Applied changes : {e.ChangesStatistics.TotalAppliedChanges}"); // e.Action = ChangeApplicationAction.Continue; // break; // case SyncStage.ApplyingInserts: // Console.WriteLine($"Applying Inserts : {e.ChangesStatistics.AppliedChanges.Where(ac => ac.State == DmRowState.Added).Sum(ac => ac.ChangesApplied) }"); // e.Action = ChangeApplicationAction.Continue; // break; // case SyncStage.ApplyingDeletes: // Console.WriteLine($"Applying Deletes : {e.ChangesStatistics.AppliedChanges.Where(ac => ac.State == DmRowState.Deleted).Sum(ac => ac.ChangesApplied) }"); // break; // case SyncStage.ApplyingUpdates: // Console.WriteLine($"Applying Updates : {e.ChangesStatistics.AppliedChanges.Where(ac => ac.State == DmRowState.Modified).Sum(ac => ac.ChangesApplied) }"); // e.Action = ChangeApplicationAction.Continue; // break; // } //}; agent.ApplyChangedFailed += ApplyChangedFailed; do { Console.Clear(); Console.WriteLine("Sync Start"); try { var s = await agent.SynchronizeAsync(); } 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); Console.WriteLine("End"); }
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 async Task ConflictUpdateUpdateClientWins(SyncConfiguration conf) { var id = Guid.NewGuid().ToString(); using (var sqlConnection = new SqlConnection(fixture.Client1ConnectionString)) { var script = $@"INSERT [ServiceTickets] ([ServiceTicketID], [Title], [Description], [StatusValue], [EscalationLevel], [Opened], [Closed], [CustomerID]) VALUES (N'{id}', N'Line for conflict', N'Description client', 1, 0, getdate(), NULL, 1)"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var server = new KestrellTestServer()) { var serverHandler = new RequestDelegate(async context => { conf.Tables = fixture.Tables; serverProvider.SetConfiguration(conf); proxyServerProvider.SerializationFormat = conf.SerializationFormat; await proxyServerProvider.HandleRequestAsync(context); }); var clientHandler = new ResponseDelegate(async(serviceUri) => { proxyClientProvider.ServiceUri = new Uri(serviceUri); proxyClientProvider.SerializationFormat = conf.SerializationFormat; var session = await agent.SynchronizeAsync(); // check statistics Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); Assert.Equal(0, session.TotalSyncConflicts); }); await server.Run(serverHandler, clientHandler); } using (var sqlConnection = new SqlConnection(fixture.Client1ConnectionString)) { var script = $@"Update [ServiceTickets] Set Title = 'Updated from Client' Where ServiceTicketId = '{id}'"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var sqlConnection = new SqlConnection(fixture.ServerConnectionString)) { var script = $@"Update [ServiceTickets] Set Title = 'Updated from Server' Where ServiceTicketId = '{id}'"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var server = new KestrellTestServer()) { var serverHandler = new RequestDelegate(async context => { conf.Tables = fixture.Tables; serverProvider.SetConfiguration(conf); proxyServerProvider.SerializationFormat = conf.SerializationFormat; // Since we move to server side, it's server to handle errors serverProvider.ApplyChangedFailed += (s, args) => { args.Action = ApplyAction.RetryWithForceWrite; }; await proxyServerProvider.HandleRequestAsync(context); }); var clientHandler = new ResponseDelegate(async(serviceUri) => { proxyClientProvider.ServiceUri = new Uri(serviceUri); proxyClientProvider.SerializationFormat = conf.SerializationFormat; SyncContext session = null; await Assert.RaisesAsync <ApplyChangeFailedEventArgs>( h => serverProvider.ApplyChangedFailed += h, h => serverProvider.ApplyChangedFailed -= h, async() => { session = await agent.SynchronizeAsync(); }); // check statistics Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); Assert.Equal(1, session.TotalSyncConflicts); }); await server.Run(serverHandler, clientHandler); } string expectedRes = string.Empty; using (var sqlConnection = new SqlConnection(fixture.ServerConnectionString)) { var script = $@"Select Title from [ServiceTickets] Where ServiceTicketID='{id}'"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); expectedRes = sqlCmd.ExecuteScalar() as string; sqlConnection.Close(); } } // check good title on client Assert.Equal("Updated from Client", expectedRes); }
public async Task ConflictUpdateUpdateClientWins(SyncConfiguration conf) { var id = Guid.NewGuid().ToString(); using (var sqlConnection = new MySqlConnection(fixture.ClientMySqlConnectionString)) { var script = $@"INSERT INTO `ServiceTickets` (`ServiceTicketID`, `Title`, `Description`, `StatusValue`, `EscalationLevel`, `Opened`, `Closed`, `CustomerID`) VALUES ('{id}', 'Line for conflict', 'Description client', 1, 0, now(), NULL, 1)"; using (var sqlCmd = new MySqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } agent.Configuration = conf; agent.Configuration.Add(fixture.Tables); var session = await agent.SynchronizeAsync(); //just check, even if it's not the real test :) // check statistics Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); Assert.Equal(0, session.TotalSyncConflicts); using (var sqlConnection = new MySqlConnection(fixture.ClientMySqlConnectionString)) { var script = $@"Update `ServiceTickets` Set Title = 'Updated from Client' Where ServiceTicketId = '{id}'"; using (var sqlCmd = new MySqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } using (var sqlConnection = new SqlConnection(fixture.ServerConnectionString)) { var script = $@"Update [ServiceTickets] Set Title = 'Updated from Server' Where ServiceTicketId = '{id}'"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); sqlCmd.ExecuteNonQuery(); sqlConnection.Close(); } } agent.ApplyChangedFailed += (s, args) => args.Action = ConflictAction.ClientWins; await Assert.RaisesAsync <ApplyChangeFailedEventArgs>( h => agent.ApplyChangedFailed += h, h => agent.ApplyChangedFailed -= h, async() => { session = await agent.SynchronizeAsync(); }); // check statistics Assert.Equal(0, session.TotalChangesDownloaded); Assert.Equal(1, session.TotalChangesUploaded); Assert.Equal(1, session.TotalSyncConflicts); string expectedRes = string.Empty; using (var sqlConnection = new SqlConnection(fixture.ServerConnectionString)) { var script = $@"Select Title from [ServiceTickets] Where ServiceTicketID='{id}'"; using (var sqlCmd = new SqlCommand(script, sqlConnection)) { sqlConnection.Open(); expectedRes = sqlCmd.ExecuteScalar() as string; sqlConnection.Close(); } } // check good title on client Assert.Equal("Updated from Client", expectedRes); }
public EmployeeItemViewModel(INavigation navigation, DatabaseService databaseService, SyncConfiguration syncConfiguration) { this.navigation = navigation; customSyncEngine = new CustomSyncEngine(databaseService, syncConfiguration); transaction = customSyncEngine.Realm.BeginWrite(); synchronizationId = databaseService.GetSynchronizationId(); IsActiveItems = new List <bool>() { true, false }; DepartmentItems = new List <ReferenceItem>(); DepartmentItems.Add(new ReferenceItem() { Id = Guid.Empty.ToString(), Name = "[None]" }); List <Department> departments = databaseService.GetDepartments().ToList(); for (int i = 0; i < departments.Count; i++) { DepartmentItems.Add(new ReferenceItem() { Id = departments[i].Id, Name = departments[i].Name }); } }