/// <summary> /// Gets changes rows count estimation, /// </summary> internal virtual async Task <(SyncContext, DatabaseChangesSelected)> InternalGetEstimatedChangesCountAsync( SyncContext context, MessageGetChangesBatch message, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress <ProgressArgs> progress) { // Call interceptor await this.InterceptAsync(new DatabaseChangesSelectingArgs(context, message, connection, transaction), cancellationToken).ConfigureAwait(false); // Create stats object to store changes count var changes = new DatabaseChangesSelected(); if (context.SyncWay == SyncWay.Upload && context.SyncType == SyncType.Reinitialize) { return(context, changes); } foreach (var syncTable in message.Schema.Tables) { // if we are in upload stage, so check if table is not download only if (context.SyncWay == SyncWay.Upload && syncTable.SyncDirection == SyncDirection.DownloadOnly) { continue; } // if we are in download stage, so check if table is not download only if (context.SyncWay == SyncWay.Download && syncTable.SyncDirection == SyncDirection.UploadOnly) { continue; } // Get Command var command = await this.GetSelectChangesCommandAsync(context, syncTable, message.Setup, message.IsNew, connection, transaction); // Set parameters this.SetSelectChangesCommonParameters(context, syncTable, message.ExcludingScopeId, message.IsNew, message.LastTimestamp, command); // launch interceptor if any var args = new TableChangesSelectingArgs(context, syncTable, command, connection, transaction); await this.InterceptAsync(args, cancellationToken).ConfigureAwait(false); if (args.Cancel || args.Command == null) { continue; } // Statistics var tableChangesSelected = new TableChangesSelected(syncTable.TableName, syncTable.SchemaName); // Get the reader using var dataReader = await args.Command.ExecuteReaderAsync().ConfigureAwait(false); while (dataReader.Read()) { bool isTombstone = false; for (var i = 0; i < dataReader.FieldCount; i++) { if (dataReader.GetName(i) == "sync_row_is_tombstone") { isTombstone = Convert.ToInt64(dataReader.GetValue(i)) > 0; break; } } // Set the correct state to be applied if (isTombstone) { tableChangesSelected.Deletes++; } else { tableChangesSelected.Upserts++; } } dataReader.Close(); // Check interceptor var changesArgs = new TableChangesSelectedArgs(context, null, tableChangesSelected, connection, transaction); await this.InterceptAsync(changesArgs, cancellationToken).ConfigureAwait(false); if (tableChangesSelected.Deletes > 0 || tableChangesSelected.Upserts > 0) { changes.TableChangesSelected.Add(tableChangesSelected); } } // Raise database changes selected var databaseChangesSelectedArgs = new DatabaseChangesSelectedArgs(context, message.LastTimestamp, null, changes, connection); this.ReportProgress(context, progress, databaseChangesSelectedArgs); await this.InterceptAsync(databaseChangesSelectedArgs, cancellationToken).ConfigureAwait(false); return(context, changes); }