示例#1
0
        /// <inheritdoc />
        public override Task<bool> ReadAsync(CancellationToken cancellationToken)
        {
            return ExecuteHelper.WithErrorTranslationAndProfiling(
                async () =>
                {
                    await PopulateMetadataAsync(cancellationToken).ConfigureAwait(false);
                    _innerList.Clear();
                    //read # values == # fields.
                    var first = await _resultSet.NextAsync(cancellationToken).ConfigureAwait(false);
                    if (first == null)
                    {
                        return false;
                    }

                    _innerList.Add(first);
                    //we expect to get full rows...
                    for (var i = 1; i < _metadata.RowType.Fields.Count; i++)
                    {
                        _innerList.Add(await _resultSet.NextAsync(cancellationToken).ConfigureAwait(false));
                    }

                    return true;
                },
                "SpannerDataReader.Read");
        }
        /// <summary>
        /// Reads the next row of values from Cloud Spanner.
        /// Important: Cloud Spanner supports limited cancellation of this task.
        /// </summary>
        /// <param name="cancellationToken">A cancellation token to cancel the read. Cloud Spanner currently
        /// supports limited cancellation while advancing the read to the next row.</param>
        /// <returns>True if another row was read.</returns>
        public override Task <bool> ReadAsync(CancellationToken cancellationToken)
        {
            return(ExecuteHelper.WithErrorTranslationAndProfiling(
                       async() =>
            {
                if (_metadata == null)
                {
                    await PopulateMetadataAsync(cancellationToken).ConfigureAwait(false);
                }
                _rowValid = false;
                _innerList.Clear();

                var first = await _resultSet.NextAsync(cancellationToken).ConfigureAwait(false);
                if (first == null)
                {
                    return false;
                }

                _innerList.Add(first);
                // We expect to get full rows...
                for (var i = 1; i < _metadata.RowType.Fields.Count; i++)
                {
                    var value = await _resultSet.NextAsync(cancellationToken).ConfigureAwait(false);
                    GaxPreconditions.CheckState(value != null, "Incomplete row returned by Spanner server");
                    _innerList.Add(value);
                }
                _rowValid = true;

                return true;
            },
                       "SpannerDataReader.Read", Logger));
        }
示例#3
0
        /// <summary>
        /// Reads the next row of values from Cloud Spanner.
        /// Important: Cloud Spanner supports limited cancellation of this task.
        /// </summary>
        /// <param name="cancellationToken">A cancellation token to cancel the read. Cloud Spanner currently
        /// supports limited cancellation while advancing the read to the next row.</param>
        /// <returns>True if another row was read.</returns>
        public override Task <bool> ReadAsync(CancellationToken cancellationToken) =>
        ExecuteHelper.WithErrorTranslationAndProfiling(async() =>
        {
            using (var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(_readTimeoutSeconds)))
            {
                var timeoutToken = timeoutCts.Token;
                using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutToken))
                {
                    try
                    {
                        var effectiveToken = linkedCts.Token;
                        if (_metadata == null)
                        {
                            await PopulateMetadataAsync(effectiveToken).ConfigureAwait(false);
                        }
                        _rowValid = false;
                        _innerList.Clear();

                        var first = await _resultSet.NextAsync(effectiveToken).ConfigureAwait(false);
                        if (first == null)
                        {
                            // If this is the first thing we've tried to read, then we know there are no rows.
                            if (_hasRows == null)
                            {
                                _hasRows = false;
                            }
                            return(false);
                        }

                        _innerList.Add(first);
                        // We expect to get full rows...
                        for (var i = 1; i < _metadata.RowType.Fields.Count; i++)
                        {
                            var value = await _resultSet.NextAsync(effectiveToken).ConfigureAwait(false);
                            GaxPreconditions.CheckState(value != null, "Incomplete row returned by Spanner server");
                            _innerList.Add(value);
                        }
                        _rowValid = true;
                        _hasRows  = true;

                        return(true);
                    }
                    // Translate timeouts from our own cancellation token into a Spanner exception.
                    // This mimics the behavior of SqlDataReader, which throws a SqlException on timeout.
                    // It's *possible* that the operation was cancelled due to the user-provided cancellation token,
                    // and that it just happens that the timeout has been fired as well... but there's a race
                    // condition anyway in that case, so it's probably reasonable to take the simple path.
                    catch (OperationCanceledException) when(timeoutToken.IsCancellationRequested)
                    {
                        throw new SpannerException(ErrorCode.DeadlineExceeded, "Read operation timed out");
                    }
                }
            }
        },
                                                       "SpannerDataReader.Read", Logger);