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