示例#1
0
 private static IAsyncEnumerable <TResult> _GroupJoin <TOuter, TInner, TKey, TResult>(
     RelationalQueryContext queryContext,
     IAsyncEnumerable <ValueBuffer> source,
     IShaper <TOuter> outerShaper,
     IShaper <TInner> innerShaper,
     Func <TInner, TKey> innerKeySelector,
     Func <TOuter, IAsyncEnumerable <TInner>, TResult> resultSelector,
     AsyncGroupJoinInclude outerGroupJoinInclude,
     AsyncGroupJoinInclude innerGroupJoinInclude)
 => new GroupJoinAsyncEnumerable <TOuter, TInner, TKey, TResult>(
     queryContext,
     source,
     outerShaper,
     innerShaper,
     innerKeySelector,
     resultSelector,
     outerGroupJoinInclude,
     innerGroupJoinInclude);
示例#2
0
 public QueryingEnumerable(RelationalQueryContext relationalQueryContext,
                           IQuerySqlGeneratorFactory querySqlGeneratorFactory,
                           ISqlExpressionFactory sqlExpressionFactory,
                           IParameterNameGeneratorFactory parameterNameGeneratorFactory,
                           SelectExpression selectExpression,
                           Func <QueryContext, DbDataReader, T, int[], ResultCoordinator, T> shaper,
                           Type contextType,
                           IDiagnosticsLogger <DbLoggerCategory.Query> logger)
 {
     _relationalQueryContext        = relationalQueryContext;
     _querySqlGeneratorFactory      = querySqlGeneratorFactory;
     _sqlExpressionFactory          = sqlExpressionFactory;
     _parameterNameGeneratorFactory = parameterNameGeneratorFactory;
     _selectExpression = selectExpression;
     _shaper           = shaper;
     _contextType      = contextType;
     _logger           = logger;
 }
示例#3
0
        internal static IAsyncEnumerable <T> _Include <T>(
            RelationalQueryContext queryContext,
            IAsyncEnumerable <T> innerResults,
            Func <T, object> entityAccessor,
            IReadOnlyList <INavigation> navigationPath,
            IReadOnlyList <Func <IAsyncIncludeRelatedValuesStrategy> > includeRelatedValuesStrategyFactories,
            bool querySourceRequiresTracking)
        {
            queryContext.BeginIncludeScope();

            var includeRelatedValuesStrategies
                = includeRelatedValuesStrategyFactories
                  .Select(f => f())
                  .ToList();

            var relatedValueBuffers
                = includeRelatedValuesStrategies
                  .Select <IAsyncIncludeRelatedValuesStrategy, AsyncRelatedEntitiesLoader>(s => s.GetRelatedValues)
                  .ToArray();

            return(innerResults
                   .Select(
                       async(result, cancellationToken) =>
            {
                await queryContext.QueryBuffer
                .IncludeAsync(
                    entityAccessor == null ? result : entityAccessor(result),                 // TODO: Compile time?
                    navigationPath,
                    relatedValueBuffers,
                    cancellationToken,
                    querySourceRequiresTracking);

                return result;
            })
                   .Finally(() =>
            {
                foreach (var includeRelatedValuesStrategy in includeRelatedValuesStrategies)
                {
                    includeRelatedValuesStrategy.Dispose();
                }

                queryContext.EndIncludeScope();
            }));
        }
示例#4
0
        internal static IEnumerable <T> _Include <T>(
            RelationalQueryContext queryContext,
            IEnumerable <T> innerResults,
            Func <T, object> entityAccessor,
            IReadOnlyList <INavigation> navigationPath,
            IReadOnlyList <Func <IIncludeRelatedValuesStrategy> > includeRelatedValuesStrategyFactories,
            bool querySourceRequiresTracking)
        {
            queryContext.BeginIncludeScope();

            var includeRelatedValuesStrategies
                = includeRelatedValuesStrategyFactories
                  .Select(f => f())
                  .ToList();

            var relatedEntitiesLoaders
                = includeRelatedValuesStrategies
                  .Select <IIncludeRelatedValuesStrategy, RelatedEntitiesLoader>(s => s.GetRelatedValues)
                  .ToArray();

            try
            {
                foreach (var innerResult in innerResults)
                {
                    queryContext.QueryBuffer
                    .Include(
                        entityAccessor == null ? innerResult : entityAccessor(innerResult),     // TODO: Compile time?
                        navigationPath,
                        relatedEntitiesLoaders,
                        querySourceRequiresTracking);

                    yield return(innerResult);
                }
            }
            finally // Need this to run even if innerResults is not fully consumed.
            {
                foreach (var includeRelatedValuesStrategy in includeRelatedValuesStrategies)
                {
                    includeRelatedValuesStrategy.Dispose();
                }

                queryContext.EndIncludeScope();
            }
        }
 public GroupJoinAsyncEnumerable(
     RelationalQueryContext queryContext,
     IAsyncEnumerable <ValueBuffer> source,
     IShaper <TOuter> outerShaper,
     IShaper <TInner> innerShaper,
     Func <TInner, TKey> innerKeySelector,
     Func <TOuter, IAsyncEnumerable <TInner>, TResult> resultSelector,
     AsyncGroupJoinInclude outerGroupJoinInclude,
     AsyncGroupJoinInclude innerGroupJoinInclude)
 {
     _queryContext          = queryContext;
     _source                = source;
     _outerShaper           = outerShaper;
     _innerShaper           = innerShaper;
     _innerKeySelector      = innerKeySelector;
     _resultSelector        = resultSelector;
     _outerGroupJoinInclude = outerGroupJoinInclude;
     _innerGroupJoinInclude = innerGroupJoinInclude;
 }
示例#6
0
        private static IAsyncEnumerable <T> _Include <T>(
            RelationalQueryContext queryContext,
            IAsyncEnumerable <T> innerResults,
            Func <T, object> entityAccessor,
            IReadOnlyList <INavigation> navigationPath,
            IReadOnlyList <Func <QueryContext, IAsyncRelatedEntitiesLoader> > relatedEntitiesLoaderFactories,
            bool querySourceRequiresTracking)
        {
            queryContext.BeginIncludeScope();

            var relatedEntitiesLoaders
                = relatedEntitiesLoaderFactories.Select(f => f(queryContext))
                  .ToArray();

            return(innerResults
                   .Select(
                       async(result, cancellationToken) =>
            {
                await queryContext.QueryBuffer
                .IncludeAsync(
                    queryContext,
                    entityAccessor == null
                                        ? result
                                        : entityAccessor(result), // TODO: Compile time?
                    navigationPath,
                    relatedEntitiesLoaders,
                    querySourceRequiresTracking,
                    cancellationToken);

                return result;
            })
                   .Finally(() =>
            {
                foreach (var relatedEntitiesLoader in relatedEntitiesLoaders)
                {
                    relatedEntitiesLoader.Dispose();
                }

                queryContext.EndIncludeScope();
            }));
        }
示例#7
0
        private static IAsyncEnumerable <T> _Include <T>(
            RelationalQueryContext queryContext,
            IAsyncEnumerable <T> innerResults,
            Func <T, object> entityAccessor,
            IReadOnlyList <INavigation> navigationPath,
            IReadOnlyList <Func <QueryContext, IAsyncRelatedEntitiesLoader> > relatedEntitiesLoaderFactories,
            bool querySourceRequiresTracking)
        {
            queryContext.BeginIncludeScope();

            var relatedEntitiesLoaders
                = relatedEntitiesLoaderFactories.Select(f => f(queryContext))
                  .ToArray();

            return(new IncludeAsyncEnumerable <T>(
                       queryContext,
                       innerResults,
                       entityAccessor,
                       navigationPath,
                       relatedEntitiesLoaders,
                       querySourceRequiresTracking));
        }
示例#8
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();
            }
        }
        // ReSharper disable once InconsistentNaming
        private static IEnumerable <TResult> _GroupJoin <TOuter, TInner, TKey, TResult>(
            RelationalQueryContext queryContext,
            IEnumerable <ValueBuffer> source,
            IShaper <TOuter> outerShaper,
            IShaper <TInner> innerShaper,
            Func <TInner, TKey> innerKeySelector,
            Func <TOuter, IEnumerable <TInner>, TResult> resultSelector,
            GroupJoinInclude outerGroupJoinInclude,
            GroupJoinInclude innerGroupJoinInclude)
        {
            var outerGroupJoinIncludeContext = outerGroupJoinInclude?.CreateIncludeContext(queryContext);
            var innerGroupJoinIncludeContext = innerGroupJoinInclude?.CreateIncludeContext(queryContext);

            try
            {
                using (var sourceEnumerator = source.GetEnumerator())
                {
                    var comparer  = EqualityComparer <TKey> .Default;
                    var hasNext   = sourceEnumerator.MoveNext();
                    var nextOuter = default(TOuter);

                    while (hasNext)
                    {
                        var outer
                            = Equals(nextOuter, default(TOuter))
                                ? outerShaper.Shape(queryContext, sourceEnumerator.Current)
                                : nextOuter;

                        nextOuter = default(TOuter);

                        outerGroupJoinIncludeContext?.Include(outer);

                        var inner  = innerShaper.Shape(queryContext, sourceEnumerator.Current);
                        var inners = new List <TInner>();

                        if (inner == null)
                        {
                            yield return(resultSelector(outer, inners));

                            hasNext = sourceEnumerator.MoveNext();
                        }
                        else
                        {
                            var currentGroupKey = innerKeySelector(inner);

                            innerGroupJoinIncludeContext?.Include(inner);

                            inners.Add(inner);

                            while (true)
                            {
                                hasNext = sourceEnumerator.MoveNext();

                                if (!hasNext)
                                {
                                    break;
                                }

                                nextOuter = outerShaper.Shape(queryContext, sourceEnumerator.Current);

                                if (!Equals(outer, nextOuter))
                                {
                                    break;
                                }

                                nextOuter = default(TOuter);

                                inner = innerShaper.Shape(queryContext, sourceEnumerator.Current);

                                if (inner == null)
                                {
                                    break;
                                }

                                var innerKey = innerKeySelector(inner);

                                if (!comparer.Equals(currentGroupKey, innerKey))
                                {
                                    break;
                                }

                                innerGroupJoinIncludeContext?.Include(inner);

                                inners.Add(inner);
                            }

                            yield return(resultSelector(outer, inners));
                        }
                    }
                }
            }
            finally
            {
                innerGroupJoinIncludeContext?.Dispose();
                outerGroupJoinIncludeContext?.Dispose();
            }
        }