/// <summary> /// Adds a single row to the end of the buffer file. INTENDED FOR SINGLE ROW INSERTION ONLY. /// </summary> /// <param name="dbDataReader">An UNREAD db data reader</param> /// <returns>The offset into the file where the row was inserted</returns> private async Task <long> AppendRowToBuffer(DbDataReader dbDataReader) { Validate.IsNotNull(nameof(dbDataReader), dbDataReader); // Sanity check to make sure that results read has started if (!hasStartedRead) { throw new InvalidOperationException(SR.QueryServiceResultSetNotRead); } // NOTE: We are no longer checking to see if the data reader has rows before reading // b/c of a quirk in SqlClient. In some scenarios, a SqlException isn't thrown until we // read. In order to get appropriate errors back to the user, we'll read first. // Returning false from .ReadAsync means there aren't any rows. // Create a storage data reader, read it, make sure there were results StorageDataReader dataReader = new StorageDataReader(dbDataReader); if (!await dataReader.ReadAsync(CancellationToken.None)) { throw new InvalidOperationException(SR.QueryServiceResultSetAddNoRows); } using (IFileStreamWriter writer = fileStreamFactory.GetWriter(outputFileName)) { // Write the row to the end of the file long currentFileOffset = totalBytesWritten; writer.Seek(currentFileOffset); totalBytesWritten += writer.WriteRow(dataReader); return(currentFileOffset); } }
/// <summary> /// Adds a single row to the end of the buffer file. INTENDED FOR SINGLE ROW INSERTION ONLY. /// </summary> /// <param name="dbDataReader">An UNREAD db data reader</param> /// <returns>The offset into the file where the row was inserted</returns> private async Task <long> AppendRowToBuffer(DbDataReader dbDataReader) { Validate.IsNotNull(nameof(dbDataReader), dbDataReader); if (!hasBeenRead) { throw new InvalidOperationException(SR.QueryServiceResultSetNotRead); } if (!dbDataReader.HasRows) { throw new InvalidOperationException(SR.QueryServiceResultSetAddNoRows); } StorageDataReader dataReader = new StorageDataReader(dbDataReader); using (IFileStreamWriter writer = fileStreamFactory.GetWriter(outputFileName)) { // Write the row to the end of the file long currentFileOffset = totalBytesWritten; writer.Seek(currentFileOffset); await dataReader.ReadAsync(CancellationToken.None); totalBytesWritten += writer.WriteRow(dataReader); return(currentFileOffset); } }
/// <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(); // Mark that result has been read hasBeenRead = true; 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; while (await dataReader.ReadAsync(cancellationToken)) { fileOffsets.Add(totalBytesWritten); totalBytesWritten += fileWriter.WriteRow(dataReader); } } // Check if resultset is 'for xml/json'. If it is, set isJson/isXml value in column metadata SingleColumnXmlJsonResultSet(); CheckForIsJson(); } finally { // Fire off a result set completion event if we have one if (ResultCompletion != null) { await ResultCompletion(this); } } }
/// <summary> /// Reads from the reader until there are no more results to read /// </summary> /// <param name="cancellationToken">Cancellation token for cancelling the query</param> public async Task ReadResultToEnd(CancellationToken cancellationToken) { try { // Mark that result has been read hasBeenRead = true; // 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; long currentFileOffset = 0; while (await dataReader.ReadAsync(cancellationToken)) { RowCount++; fileOffsets.Add(currentFileOffset); currentFileOffset += fileWriter.WriteRow(dataReader); } } // Check if resultset is 'for xml/json'. If it is, set isJson/isXml value in column metadata SingleColumnXmlJsonResultSet(); } finally { // Fire off a result set completion event if we have one if (ResultCompletion != null) { await ResultCompletion(this); } } }
/// <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); } }