public void OutOfOrderTest() { var result = RowSorter.MaybeSortRows( Row("1", "2", "3"), new List <TableRow> { Row("2", "3", "1"), Row("4", "5", "6") }); CollectionAssert.AreEqual(new[] { "6", "4", "5" }, result.Single().Values()); }
public void UnsortableTest() { var result = RowSorter.MaybeSortRows( Row("1", "2", "3"), new List <TableRow> { Row("x", "y", "z"), Row("4", "5", "6") }).ToList(); Assert.AreEqual(2, result.Count); CollectionAssert.AreEqual(new[] { "x", "y", "z" }, result[0].Values()); CollectionAssert.AreEqual(new[] { "4", "5", "6" }, result[1].Values()); }
/// <summary> /// Pull out sorted batches from the RowSorter instance and save them using the IBatchHandler implementation. /// Also return the first batch as an output. /// </summary> /// <param name="rowSorter">RowSorter instance.</param> /// <returns>The first batch pulled from the RowSorter.</returns> private Batch SaveBatchesAndReturnFirstBatch(RowSorter rowSorter) { // Get an enumerator over the batch list. IEnumerable<RowSorter.SortedBatch> batchEnumerator = rowSorter.PullSortedBatches(); // Prepare a batch header instance. The BatchCode will be the folder name under which we will write files corresponding // to each sorted batch. Every batch will have a knowledge that contains the information in the batch. So we have to combine // the existing client knowledge with the batch knowledge before returning it back to the caller. var header = new BatchHeader { BatchCode = Guid.NewGuid(), // New batch code. BatchFileNames = new List<string>() }; var batchList = new List<Batch>(); Guid batchName = Guid.NewGuid(); Guid nextBatchName = Guid.NewGuid(); foreach (var sortedBatch in batchEnumerator) { // Create a new batch instance. var b = new Batch { BatchCode = header.BatchCode, FileName = batchName.ToString(), // Random file name LearnedKnowledge = sortedBatch.sortedDataSetKnowledge.Serialize(), Data = sortedBatch.sortedDataSet, ClientScopeName = _clientScopeName, NextBatch = nextBatchName }; header.BatchFileNames.Add(b.FileName); batchList.Add(b); // Set the batch names. batchName = nextBatchName; nextBatchName = Guid.NewGuid(); } // If there are no batches, just return. if (0 == batchList.Count) { return null; } // Set properties for the last batch. batchList[batchList.Count - 1].IsLastBatch = true; batchList[batchList.Count - 1].NextBatch = null; // Only save if we have more than 1 batch. if (batchList.Count > 1) { // Save all but the first batch, since we are sending that to the client as a response to the current request. _batchHandler.SaveBatches(batchList.Skip(1).ToList(), header); } // Return the first batch. return batchList[0]; }
/// <summary> /// Get a new instance of the RowSorter class using the knowledge passed as a parameter. /// This is used to pull out sorted batches with learned knowledge to send to the client. /// </summary> /// <param name="clientKnowledge">Knowledge to initialize the RowSorter instance.</param> /// <returns>An instance of the RowSorter class.</returns> private RowSorter GetRowSorter(SyncKnowledge clientKnowledge) { DbSyncScopeDescription scopeDescription = GetScopeDescription(); Debug.Assert(null != scopeDescription); /* Note: The RowSorter class and dependencies are copied over from the 2.1 providers. * If an when we decide to make this assembly a friend of the provider assembly, * we can remove the local copy of the source code. */ // Initialize an instance of the RowSorter class. var rowSorter = new RowSorter(clientKnowledge, _clientScopeName, _configuration.DownloadBatchSizeInKB.Value); // Add all the tables to the RowSorter instance. foreach (DbSyncTableDescription table in scopeDescription.Tables) { // Get primary keys. List<string> pkColumns = table.PkColumns.Select(c => c.UnquotedName).ToList(); // Set up the tables in the RowSorter class. // The DataTable names will be equal to the UnquotedGlobalName // property value. rowSorter.AddTable(table.UnquotedGlobalName, pkColumns); } return rowSorter; }