public async Task <bool> MoveNext(CancellationToken cancellationToken)
                {
                    if (_dataReader == null)
                    {
                        await _relationalQueryContext.Connection.OpenAsync(cancellationToken);

                        try
                        {
                            var relationalCommand
                                = _shaperCommandContext
                                  .GetRelationalCommand(_relationalQueryContext.ParameterValues, _relationalQueryContext);

                            _dataReader
                                = await relationalCommand.ExecuteReaderAsync(
                                      _relationalQueryContext.Connection,
                                      _relationalQueryContext.ParameterValues,
                                      _relationalQueryContext.CommandLogger,
                                      cancellationToken);
                        }
                        catch
                        {
                            //  If failure happens creating the data reader, then it won't be available to
                            //  handle closing the connection, so do it explicitly here to preserve ref counting.
                            _relationalQueryContext.Connection.Close();

                            throw;
                        }

                        _dbDataReader = _dataReader.DbDataReader;
                    }

                    using (await _relationalQueryContext.ConcurrencyDetector
                           .EnterCriticalSectionAsync(cancellationToken))
                    {
                        bool hasNext;

                        try
                        {
                            hasNext = await _dbDataReader.ReadAsync(cancellationToken);
                        }
                        catch (Exception exception)
                        {
                            _logger.QueryIterationFailed(_contextType, exception);

                            throw;
                        }

                        Current
                            = hasNext
                                ? _materializer(_dbDataReader, _relationalQueryContext.Context)
                                : default;

                        return(hasNext);
                    }
                }
Exemplo n.º 2
0
        // ReSharper disable once InconsistentNaming
        private static IEnumerable <TEntity> _FastQuery <TEntity>(
            RelationalQueryContext relationalQueryContext,
            ShaperCommandContext shaperCommandContext,
            Func <DbDataReader, DbContext, TEntity> materializer,
            Type contextType,
            IDiagnosticsLogger <DbLoggerCategory.Query> logger)
        {
            relationalQueryContext.Connection.Open();

            RelationalDataReader dataReader;

            try
            {
                var relationalCommand
                    = shaperCommandContext
                      .GetRelationalCommand(relationalQueryContext.ParameterValues, relationalQueryContext);

                dataReader
                    = relationalCommand.ExecuteReader(
                          relationalQueryContext.Connection,
                          relationalQueryContext.ParameterValues,
                          relationalQueryContext.CommandLogger);
            }
            catch
            {
                // If failure happens creating the data reader, then it won't be available to
                // handle closing the connection, so do it explicitly here to preserve ref counting.
                relationalQueryContext.Connection.Close();

                throw;
            }

            var dbDataReader = dataReader.DbDataReader;

            try
            {
                using (dataReader)
                {
                    using (relationalQueryContext.ConcurrencyDetector.EnterCriticalSection()) // TODO: IDisposable box?
                    {
                        while (true)
                        {
                            bool hasNext;

                            try
                            {
                                hasNext = dataReader.Read();
                            }
                            catch (Exception exception)
                            {
                                logger.QueryIterationFailed(contextType, exception);

                                throw;
                            }

                            if (hasNext)
                            {
                                yield return(materializer(dbDataReader, relationalQueryContext.Context));
                            }
                            else
                            {
                                yield break;
                            }
                        }
                    }
                }
            }
            finally
            {
                relationalQueryContext.Connection?.Close();
                relationalQueryContext.Dispose();
            }
        }