Exemplo n.º 1
0
        /// <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);
            }
        }
Exemplo n.º 2
0
        /// <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);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Creates a new result set and initializes its state
        /// </summary>
        /// <param name="reader">The reader from executing a query</param>
        /// <param name="factory">Factory for creating a reader/writer</param>
        public ResultSet(DbDataReader reader, IFileStreamFactory factory)
        {
            // Sanity check to make sure we got a reader
            Validate.IsNotNull(nameof(reader), SR.QueryServiceResultSetReaderNull);

            DataReader = new StorageDataReader(reader);

            // Initialize the storage
            outputFileName = factory.CreateFile();
            FileOffsets    = new LongList <long>();

            // Store the factory
            fileStreamFactory = factory;
            hasBeenRead       = false;
            saveTasks         = new ConcurrentDictionary <string, Task>();
        }
Exemplo n.º 4
0
        /// <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);
                }
            }
        }
Exemplo n.º 5
0
        /// <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);
            }
        }
Exemplo n.º 6
0
        /// <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);
            }
        }