/// <summary> /// Reads from the reader until there are no more results to read /// </summary> /// <param name="dbDataReader">The data reader for getting results from the db</param> /// <param name="cancellationToken">Cancellation token for cancelling the query</param> public async Task ReadResultToEnd(DbDataReader dbDataReader, CancellationToken cancellationToken) { // Sanity check to make sure we got a reader // Validate.IsNotNull(nameof(dbDataReader), dbDataReader); try { // Verify the request hasn't been cancelled cancellationToken.ThrowIfCancellationRequested(); StorageDataReader dataReader = new StorageDataReader(dbDataReader); // Open a writer for the file // var fileWriter = fileStreamFactory.GetWriter(outputFileName); using (fileWriter) { // If we can initialize the columns using the column schema, use that // if (!dataReader.DbDataReader.CanGetColumnSchema()) { throw new InvalidOperationException(SR.QueryServiceResultSetNoColumnSchema); } Columns = dataReader.Columns; // Check if result set is 'for xml/json'. If it is, set isJson/isXml value in column metadata // SingleColumnXmlJsonResultSet(); // Mark that read of result has started // hasStartedRead = true; while (await dataReader.ReadAsync(cancellationToken)) { fileOffsets.Add(totalBytesWritten); totalBytesWritten += fileWriter.WriteRow(dataReader); // If we have never triggered the timer to start sending the results available/updated notification // then: Trigger the timer to start sending results update notification // if (LastUpdatedSummary == null) { // Invoke the timer to send available/update result set notification immediately // resultsTimer.Change(0, Timeout.Infinite); } } CheckForIsJson(); } } finally { hasCompletedRead = true; // set the flag to indicate that we are done reading // Make a final call to ResultUpdated by invoking the timer to send update result set notification immediately // resultsTimer.Change(0, Timeout.Infinite); // and finally: // Make a call to send ResultCompletion and await for it to Complete // await(ResultCompletion?.Invoke(this) ?? Task.CompletedTask); } }
/// <summary> /// Reads from the reader until there are no more results to read /// </summary> /// <param name="dbDataReader">The data reader for getting results from the db</param> /// <param name="cancellationToken">Cancellation token for cancelling the query</param> public async Task ReadResultToEnd(DbDataReader dbDataReader, CancellationToken cancellationToken) { // Sanity check to make sure we got a reader // Validate.IsNotNull(nameof(dbDataReader), dbDataReader); Task availableTask = null; try { // Verify the request hasn't been cancelled cancellationToken.ThrowIfCancellationRequested(); StorageDataReader dataReader = new StorageDataReader(dbDataReader); // Open a writer for the file // var fileWriter = fileStreamFactory.GetWriter(outputFileName); using (fileWriter) { // If we can initialize the columns using the column schema, use that // if (!dataReader.DbDataReader.CanGetColumnSchema()) { throw new InvalidOperationException(SR.QueryServiceResultSetNoColumnSchema); } Columns = dataReader.Columns; // Check if result set is 'for xml/json'. If it is, set isJson/isXml value in column metadata // SingleColumnXmlJsonResultSet(); // Mark that read of result has started // hasStartedRead = true; // Invoke the SendCurrentResults() asynchronously that will send the results available notification // and also trigger the timer to send periodic updates. // availableTask = SendCurrentResults(); while (await dataReader.ReadAsync(cancellationToken)) { fileOffsets.Add(totalBytesWritten); totalBytesWritten += fileWriter.WriteRow(dataReader); } CheckForIsJson(); } } finally { // await the completion of available notification in case it is not already done before proceeding // await availableTask; // now set the flag to indicate that we are done reading. this equates to Complete flag to be marked 'True' in any future notifications. // hasCompletedRead = true; // Make a final call to SendCurrentResults() and await its completion. If the previously scheduled task already took care of latest status send then this should be a no-op // await SendCurrentResults(); // and finally: // Make a call to send ResultCompletion and await its completion. This is just for backward compatibility with older protocol // await(ResultCompletion?.Invoke(this) ?? Task.CompletedTask); } }