Beispiel #1
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public QueryCompiler(
            [NotNull] IQueryContextFactory queryContextFactory,
            [NotNull] ICompiledQueryCache compiledQueryCache,
            [NotNull] ICompiledQueryCacheKeyGenerator compiledQueryCacheKeyGenerator,
            [NotNull] IDatabase database,
            [NotNull] IDiagnosticsLogger <DbLoggerCategory.Query> logger,
            [NotNull] ICurrentDbContext currentContext,
            [NotNull] IQueryModelGenerator queryModelGenerator,
            [NotNull] IEvaluatableExpressionFilter evaluatableExpressionFilter,
            [NotNull] IModel model)
        {
            Check.NotNull(queryContextFactory, nameof(queryContextFactory));
            Check.NotNull(compiledQueryCache, nameof(compiledQueryCache));
            Check.NotNull(compiledQueryCacheKeyGenerator, nameof(compiledQueryCacheKeyGenerator));
            Check.NotNull(database, nameof(database));
            Check.NotNull(logger, nameof(logger));
            Check.NotNull(currentContext, nameof(currentContext));
            Check.NotNull(evaluatableExpressionFilter, nameof(evaluatableExpressionFilter));
            Check.NotNull(model, nameof(model));

            _queryContextFactory            = queryContextFactory;
            _compiledQueryCache             = compiledQueryCache;
            _compiledQueryCacheKeyGenerator = compiledQueryCacheKeyGenerator;
            _database    = database;
            _logger      = logger;
            _contextType = currentContext.Context.GetType();
            _evaluatableExpressionFilter = evaluatableExpressionFilter;
            _model = model;
        }
        private static Func <QueryContext, TResult> CompileAsyncQueryCore <TResult>(
            Expression query,
            IQueryModelGenerator queryModelGenerator,
            IDatabase database)
        {
            var queryModel = queryModelGenerator.ParseQuery(query);

            var resultItemType
                = (queryModel.GetOutputDataInfo()
                   as StreamedSequenceInfo)?.ResultItemType
                  ?? typeof(TResult).TryGetSequenceType();

            try
            {
                return((Func <QueryContext, TResult>)CompileAsyncQueryMethod
                       .MakeGenericMethod(resultItemType)
                       .Invoke(database, new object[] { queryModel }));
            }
            catch (TargetInvocationException e)
            {
                ExceptionDispatchInfo.Capture(e.InnerException).Throw();

                throw;
            }
        }
        public CustomQueryCompiler(IQueryContextFactory queryContextFactory, ICompiledQueryCache compiledQueryCache, ICompiledQueryCacheKeyGenerator compiledQueryCacheKeyGenerator
                                   , IDatabase database, IDiagnosticsLogger <DbLoggerCategory.Query> logger, ICurrentDbContext currentContext, IQueryModelGenerator queryModelGenerator, IEvaluatableExpressionFilter evaluatableExpressionFilter)
            : base(queryContextFactory, compiledQueryCache, compiledQueryCacheKeyGenerator, database, logger, currentContext, queryModelGenerator)
        {
            Check.NotNull(queryContextFactory, nameof(queryContextFactory));
            Check.NotNull(compiledQueryCache, nameof(compiledQueryCache));
            Check.NotNull(compiledQueryCacheKeyGenerator, nameof(compiledQueryCacheKeyGenerator));
            Check.NotNull(database, nameof(database));
            Check.NotNull(logger, nameof(logger));
            Check.NotNull(currentContext, nameof(currentContext));
            Check.NotNull(evaluatableExpressionFilter, nameof(evaluatableExpressionFilter));

            _queryContextFactory            = queryContextFactory;
            _compiledQueryCache             = compiledQueryCache;
            _compiledQueryCacheKeyGenerator = compiledQueryCacheKeyGenerator;
            _database            = database;
            _logger              = logger;
            _contextType         = currentContext.Context.GetType();
            _queryModelGenerator = queryModelGenerator;

            _logFormatter = (queryKey, ex) => $"Cache hit for query [0x{queryKey}] with: {ex?.Message ?? "no error"}";

            _cacheableOptions = currentContext.Context
                                .GetService <IDbContextServices>()
                                .ContextOptions
                                .FindExtension <CacheableOptionsExtension>();

            _cacheProvider = currentContext.Context.GetService <ICacheProvider>();
        }
        public CustomQueryCompiler(
            IQueryContextFactory queryContextFactory,
            ICompiledQueryCache compiledQueryCache,
            ICompiledQueryCacheKeyGenerator compiledQueryCacheKeyGenerator,
            IDatabase database,
            IDiagnosticsLogger <DbLoggerCategory.Query> logger,
            ICurrentDbContext currentContext,
            IQueryModelGenerator queryModelGenerator,
            IEvaluatableExpressionFilter evaluableExpressionFilter)
            : base(queryContextFactory, compiledQueryCache, compiledQueryCacheKeyGenerator, database, logger, currentContext, queryModelGenerator)
        {
            Check.NotNull(queryContextFactory, nameof(queryContextFactory));
            Check.NotNull(compiledQueryCache, nameof(compiledQueryCache));
            Check.NotNull(compiledQueryCacheKeyGenerator, nameof(compiledQueryCacheKeyGenerator));
            Check.NotNull(database, nameof(database));
            Check.NotNull(logger, nameof(logger));
            Check.NotNull(currentContext, nameof(currentContext));
            Check.NotNull(evaluableExpressionFilter, nameof(evaluableExpressionFilter));

            _queryModelGenerator = queryModelGenerator;

            _cacheProvider = currentContext.Context.GetService <ICacheProvider>();

            _xxHash = xxHashFactory.Instance.Create(new xxHashConfig()
            {
                HashSizeInBits = 64
            });
        }
 public ScopeFilterModelExpressionApplyingExpressionVisitor(QueryCompilationContext queryCompilationContext,
                                                            IQueryModelGenerator queryModelGenerator, EntityQueryModelVisitor entityQueryModelVisitor, IScopeFilterStore store)
     : base(queryCompilationContext, queryModelGenerator, entityQueryModelVisitor)
 {
     _queryCompilationContext = queryCompilationContext;
     _queryModelGenerator     = queryModelGenerator;
     _store = store;
 }
        private static Func <QueryContext, TResult> CompileQueryCore <TResult>(
            Expression query,
            IModel model,
            IQueryModelGenerator queryModelGenerator,
            IDatabase database,
            IDiagnosticsLogger <DbLoggerCategory.Query> logger,
            Type contextType)
        {
            query = ExpandNavigations(query, model);

            var queryModel = queryModelGenerator.ParseQuery(query);

            // this is temporary, until relinq is removed
            var tirev = new TransparentIdentifierRemovingVisitor();

            queryModel.TransformExpressions(tirev.Visit);

            var atasev = new AnonymousObjectAccessSimplifyingVisitor();

            queryModel.TransformExpressions(atasev.Visit);

            var resultItemType
                = (queryModel.GetOutputDataInfo()
                   as StreamedSequenceInfo)?.ResultItemType
                  ?? typeof(TResult);

            if (resultItemType == typeof(TResult))
            {
                var compiledQuery = database.CompileQuery <TResult>(queryModel);

                return(qc =>
                {
                    try
                    {
                        return compiledQuery(qc).First();
                    }
                    catch (Exception exception)
                    {
                        logger.QueryIterationFailed(contextType, exception);

                        throw;
                    }
                });
            }

            try
            {
                return((Func <QueryContext, TResult>)CompileQueryMethod
                       .MakeGenericMethod(resultItemType)
                       .Invoke(database, new object[] { queryModel }));
            }
            catch (TargetInvocationException e)
            {
                ExceptionDispatchInfo.Capture(e.InnerException).Throw();

                throw;
            }
        }
Beispiel #7
0
        private static Func <QueryContext, IAsyncEnumerable <TResult> > CompileAsyncQueryCore <TResult>(
            Expression query,
            IQueryModelGenerator queryModelGenerator,
            IDatabase database)
        {
            var queryModel = queryModelGenerator.ParseQuery(query);

            return(database.CompileAsyncQuery <TResult>(queryModel));
        }
Beispiel #8
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public FilterApplyingExpressionVisitor(
            [NotNull] QueryCompilationContext queryCompilationContext,
            [NotNull] IQueryModelGenerator queryModelGenerator)
        {
            Check.NotNull(queryCompilationContext, nameof(queryCompilationContext));
            Check.NotNull(queryModelGenerator, nameof(queryModelGenerator));

            _queryCompilationContext = queryCompilationContext;
            _queryModelGenerator     = queryModelGenerator;
        }
 public ExpressionVisitor(
     QueryCompilationContext compilationContext,
     IQueryModelGenerator generator,
     EntityQueryModelVisitor visitor) :
     base(compilationContext, generator, visitor)
 {
     this.compilationContext = compilationContext;
     this.generator          = generator;
     instanceFilters         = filters.Value;
     parameters = (IParameterValues)parameterField.GetValue(this);
 }
Beispiel #10
0
        public static string ToSql <TEntity>(this IQueryable <TEntity> query, DbContext dbCtx)
        {
            IQueryModelGenerator        modelGenerator          = dbCtx.GetService <IQueryModelGenerator>();
            QueryModel                  queryModel              = modelGenerator.ParseQuery(query.Expression);
            DatabaseDependencies        databaseDependencies    = dbCtx.GetService <DatabaseDependencies>();
            QueryCompilationContext     queryCompilationContext = databaseDependencies.QueryCompilationContextFactory.Create(false);
            RelationalQueryModelVisitor modelVisitor            = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor();

            modelVisitor.CreateQueryExecutor <TEntity>(queryModel);
            var sql = modelVisitor.Queries.First().ToString();

            return(sql);
        }
Beispiel #11
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public ModelExpressionApplyingExpressionVisitor(
            [NotNull] QueryCompilationContext queryCompilationContext,
            [NotNull] IQueryModelGenerator queryModelGenerator,
            [NotNull] EntityQueryModelVisitor entityQueryModelVisitor)
        {
            Check.NotNull(queryCompilationContext, nameof(queryCompilationContext));
            Check.NotNull(queryModelGenerator, nameof(queryModelGenerator));
            Check.NotNull(entityQueryModelVisitor, nameof(entityQueryModelVisitor));

            _queryCompilationContext = queryCompilationContext;
            _queryModelGenerator     = queryModelGenerator;
            _entityQueryModelVisitor = entityQueryModelVisitor;
        }
 /// <summary>
 ///     Clones this dependency parameter object with one service replaced.
 /// </summary>
 /// <param name="queryModelGenerator"> A replacement for the current dependency of this type. </param>
 /// <returns> A new parameter object with the given service replaced. </returns>
 public EntityQueryModelVisitorDependencies With([NotNull] IQueryModelGenerator queryModelGenerator)
 => new EntityQueryModelVisitorDependencies(
     QueryOptimizer,
     QuerySourceTracingExpressionVisitorFactory,
     EntityResultFindingExpressionVisitorFactory,
     EagerLoadingExpressionVisitorFactory,
     TaskBlockingExpressionVisitor,
     MemberAccessBindingExpressionVisitorFactory,
     ProjectionExpressionVisitorFactory,
     EntityQueryableExpressionVisitorFactory,
     QueryAnnotationExtractor,
     ResultOperatorHandler,
     EntityMaterializerSource,
     ExpressionPrinter,
     queryModelGenerator);
        /// <summary>
        ///     <para>
        ///         Creates the service dependencies parameter object for a <see cref="EntityQueryModelVisitorFactory" />.
        ///     </para>
        ///     <para>
        ///         This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///         directly from your code. This API may change or be removed in future releases.
        ///     </para>
        ///     <para>
        ///         Do not call this constructor directly from either provider or application code as it may change
        ///         as new dependencies are added. Instead, use this type in your constructor so that an instance
        ///         will be created and injected automatically by the dependency injection container. To create
        ///         an instance with some dependent services replaced, first resolve the object from the dependency
        ///         injection container, then replace selected services using the 'With...' methods. Do not call
        ///         the constructor at any point in this process.
        ///     </para>
        /// </summary>
        /// <param name="queryOptimizer"> The <see cref="IQueryOptimizer" /> to be used when processing the query. </param>
        /// <param name="navigationRewritingExpressionVisitorFactory">
        ///     The <see cref="INavigationRewritingExpressionVisitorFactory" /> to be used when
        ///     processing the query.
        /// </param>
        /// <param name="querySourceTracingExpressionVisitorFactory">
        ///     The <see cref="IQuerySourceTracingExpressionVisitorFactory" /> to be used when
        ///     processing the query.
        /// </param>
        /// <param name="entityResultFindingExpressionVisitorFactory">
        ///     The <see cref="IEntityResultFindingExpressionVisitorFactory" /> to be used when
        ///     processing the query.
        /// </param>
        /// <param name="eagerLoadingExpressionVisitorFactory">
        ///     The <see cref="IEagerLoadingExpressionVisitorFactory" /> to be used when
        ///     processing the query.
        /// </param>
        /// <param name="taskBlockingExpressionVisitor"> The <see cref="ITaskBlockingExpressionVisitor" /> to be used when processing the query. </param>
        /// <param name="memberAccessBindingExpressionVisitorFactory">
        ///     The <see cref="IMemberAccessBindingExpressionVisitorFactory" /> to be used when
        ///     processing the query.
        /// </param>
        /// <param name="projectionExpressionVisitorFactory">
        ///     The <see cref="IProjectionExpressionVisitorFactory" /> to be used when processing the
        ///     query.
        /// </param>
        /// <param name="entityQueryableExpressionVisitorFactory">
        ///     The <see cref="IEntityQueryableExpressionVisitorFactory" /> to be used when
        ///     processing the query.
        /// </param>
        /// <param name="queryAnnotationExtractor"> The <see cref="IQueryAnnotationExtractor" /> to be used when processing the query. </param>
        /// <param name="resultOperatorHandler"> The <see cref="IResultOperatorHandler" /> to be used when processing the query. </param>
        /// <param name="entityMaterializerSource"> The <see cref="IEntityMaterializerSource" /> to be used when processing the query. </param>
        /// <param name="expressionPrinter"> The <see cref="IExpressionPrinter" /> to be used when processing the query. </param>
        /// <param name="queryModelGenerator"> The <see cref="IQueryModelGenerator" /> to be used when processing the query. </param>
        public EntityQueryModelVisitorDependencies(
            [NotNull] IQueryOptimizer queryOptimizer,
            [NotNull] INavigationRewritingExpressionVisitorFactory navigationRewritingExpressionVisitorFactory,
            [NotNull] IQuerySourceTracingExpressionVisitorFactory querySourceTracingExpressionVisitorFactory,
            [NotNull] IEntityResultFindingExpressionVisitorFactory entityResultFindingExpressionVisitorFactory,
            [NotNull] IEagerLoadingExpressionVisitorFactory eagerLoadingExpressionVisitorFactory,
            [NotNull] ITaskBlockingExpressionVisitor taskBlockingExpressionVisitor,
            [NotNull] IMemberAccessBindingExpressionVisitorFactory memberAccessBindingExpressionVisitorFactory,
            [NotNull] IProjectionExpressionVisitorFactory projectionExpressionVisitorFactory,
            [NotNull] IEntityQueryableExpressionVisitorFactory entityQueryableExpressionVisitorFactory,
            [NotNull] IQueryAnnotationExtractor queryAnnotationExtractor,
            [NotNull] IResultOperatorHandler resultOperatorHandler,
            [NotNull] IEntityMaterializerSource entityMaterializerSource,
            [NotNull] IExpressionPrinter expressionPrinter,
            [NotNull] IQueryModelGenerator queryModelGenerator)
        {
            Check.NotNull(queryOptimizer, nameof(queryOptimizer));
            Check.NotNull(navigationRewritingExpressionVisitorFactory, nameof(navigationRewritingExpressionVisitorFactory));
            Check.NotNull(querySourceTracingExpressionVisitorFactory, nameof(querySourceTracingExpressionVisitorFactory));
            Check.NotNull(entityResultFindingExpressionVisitorFactory, nameof(entityResultFindingExpressionVisitorFactory));
            Check.NotNull(eagerLoadingExpressionVisitorFactory, nameof(eagerLoadingExpressionVisitorFactory));
            Check.NotNull(taskBlockingExpressionVisitor, nameof(taskBlockingExpressionVisitor));
            Check.NotNull(memberAccessBindingExpressionVisitorFactory, nameof(memberAccessBindingExpressionVisitorFactory));
            Check.NotNull(projectionExpressionVisitorFactory, nameof(projectionExpressionVisitorFactory));
            Check.NotNull(entityQueryableExpressionVisitorFactory, nameof(entityQueryableExpressionVisitorFactory));
            Check.NotNull(queryAnnotationExtractor, nameof(queryAnnotationExtractor));
            Check.NotNull(resultOperatorHandler, nameof(resultOperatorHandler));
            Check.NotNull(entityMaterializerSource, nameof(entityMaterializerSource));
            Check.NotNull(expressionPrinter, nameof(expressionPrinter));
            Check.NotNull(queryModelGenerator, nameof(queryModelGenerator));

            QueryOptimizer = queryOptimizer;
            NavigationRewritingExpressionVisitorFactory = navigationRewritingExpressionVisitorFactory;
            QuerySourceTracingExpressionVisitorFactory  = querySourceTracingExpressionVisitorFactory;
            EntityResultFindingExpressionVisitorFactory = entityResultFindingExpressionVisitorFactory;
            EagerLoadingExpressionVisitorFactory        = eagerLoadingExpressionVisitorFactory;
            TaskBlockingExpressionVisitor = taskBlockingExpressionVisitor;
            MemberAccessBindingExpressionVisitorFactory = memberAccessBindingExpressionVisitorFactory;
            ProjectionExpressionVisitorFactory          = projectionExpressionVisitorFactory;
            EntityQueryableExpressionVisitorFactory     = entityQueryableExpressionVisitorFactory;
            QueryAnnotationExtractor = queryAnnotationExtractor;
            ResultOperatorHandler    = resultOperatorHandler;
            EntityMaterializerSource = entityMaterializerSource;
            ExpressionPrinter        = expressionPrinter;
            QueryModelGenerator      = queryModelGenerator;
        }
 public CustomQueryCompiler(IQueryContextFactory queryContextFactory,
                            ICompiledQueryCache compiledQueryCache,
                            ICompiledQueryCacheKeyGenerator compiledQueryCacheKeyGenerator,
                            IDatabase database,
                            IDiagnosticsLogger <DbLoggerCategory.Query> logger,
                            ICurrentDbContext currentContext,
                            IQueryModelGenerator queryModelGenerator)
     : base(queryContextFactory,
            compiledQueryCache,
            compiledQueryCacheKeyGenerator,
            database,
            logger,
            currentContext,
            queryModelGenerator)
 {
     _logger = logger.Logger;
 }
Beispiel #15
0
        private static Func <QueryContext, TResult> CompileQueryCore <TResult>(
            Expression query,
            IQueryModelGenerator queryModelGenerator,
            IDatabase database,
            IDiagnosticsLogger <DbLoggerCategory.Query> logger,
            Type contextType)
        {
            var queryModel = queryModelGenerator.ParseQuery(query);

            var resultItemType
                = (queryModel.GetOutputDataInfo()
                   as StreamedSequenceInfo)?.ResultItemType
                  ?? typeof(TResult);

            if (resultItemType == typeof(TResult))
            {
                var compiledQuery = database.CompileQuery <TResult>(queryModel);

                return(qc =>
                {
                    try
                    {
                        return compiledQuery(qc).First();
                    }
                    catch (Exception exception)
                    {
                        logger.QueryIterationFailed(contextType, exception);

                        throw;
                    }
                });
            }

            try
            {
                return((Func <QueryContext, TResult>)CompileQueryMethod
                       .MakeGenericMethod(resultItemType)
                       .Invoke(database, new object[] { queryModel }));
            }
            catch (TargetInvocationException e)
            {
                ExceptionDispatchInfo.Capture(e.InnerException).Throw();

                throw;
            }
        }
        public static string ToSql <TEntity>(this IQueryable <TEntity> queryable)
            where TEntity : class
        {
            if (!(queryable is EntityQueryable <TEntity>) && !(queryable is InternalDbSet <TEntity>))
            {
                throw new ArgumentException();
            }

            IQueryCompiler       queryCompiler       = (IQueryCompiler)_queryCompilerField.GetValue(queryable.Provider);
            IQueryModelGenerator queryModelGenerator = (IQueryModelGenerator)_queryModelGeneratorField.GetValue(queryCompiler);
            QueryModel           queryModel          = queryModelGenerator.ParseQuery(queryable.Expression);
            object database = _databaseField.GetValue(queryCompiler);
            IQueryCompilationContextFactory queryCompilationContextFactory = ((DatabaseDependencies)_dependenciesProperty.GetValue(database)).QueryCompilationContextFactory;
            QueryCompilationContext         queryCompilationContext        = queryCompilationContextFactory.Create(false);
            RelationalQueryModelVisitor     modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor();

            modelVisitor.CreateQueryExecutor <TEntity>(queryModel);
            return(modelVisitor.Queries.Join(Environment.NewLine + Environment.NewLine));
        }
Beispiel #17
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public ModelExpressionApplyingExpressionVisitor(
            [NotNull] QueryCompilationContext queryCompilationContext,
            [NotNull] IQueryModelGenerator queryModelGenerator,
            [NotNull] EntityQueryModelVisitor entityQueryModelVisitor)
        {
            Check.NotNull(queryCompilationContext, nameof(queryCompilationContext));
            Check.NotNull(queryModelGenerator, nameof(queryModelGenerator));
            Check.NotNull(entityQueryModelVisitor, nameof(entityQueryModelVisitor));

            _queryCompilationContext = queryCompilationContext;
            _queryModelGenerator     = queryModelGenerator;
            _entityQueryModelVisitor = entityQueryModelVisitor;

            _parameterExtractingExpressionVisitor = new ParameterExtractingExpressionVisitor(
                ((QueryModelGenerator)queryModelGenerator).EvaluatableExpressionFilter,
                _parameters,
                _queryCompilationContext.ContextType,
                _queryCompilationContext.Logger,
                parameterize: false,
                generateContextAccessors: true);
        }
        private static string getExpressionKeyHash(
            IQueryCompiler queryCompiler,
            IQueryModelGenerator queryModelGenerator,
            IEFCacheKeyHashProvider cacheKeyHashProvider,
            Expression expression)
        {
            var queryContextFactory = (IQueryContextFactory)_queryContextFactoryField.GetValue(queryCompiler);
            var queryContext        = queryContextFactory.Create();
            var logger = (IDiagnosticsLogger <DbLoggerCategory.Query>)_loggerField.GetValue(queryCompiler);

            expression = queryModelGenerator.ExtractParameters(logger, expression, queryContext);

            var expressionKey   = $"{ExpressionEqualityComparer.Instance.GetHashCode(expression)};";
            var parameterValues = queryContext.ParameterValues;

            if (parameterValues.Any())
            {
                expressionKey = parameterValues.Aggregate(expressionKey, (current, item) => current + $"{item.Key}={item.Value?.GetHashCode()};");
            }
            return(cacheKeyHashProvider.ComputeHash(expressionKey));
        }
        private static Func <QueryContext, TResult> CompileAsyncQueryCore <TResult>(
            Expression query,
            IModel model,
            IQueryModelGenerator queryModelGenerator,
            IDatabase database)
        {
            query = ExpandNavigations(query, model);

            var queryModel = queryModelGenerator.ParseQuery(query);

            // this is temporary, until relinq is removed
            var tirev = new TransparentIdentifierRemovingVisitor();

            queryModel.TransformExpressions(tirev.Visit);

            var atasev = new AnonymousObjectAccessSimplifyingVisitor();

            queryModel.TransformExpressions(atasev.Visit);

            var resultItemType
                = (queryModel.GetOutputDataInfo()
                   as StreamedSequenceInfo)?.ResultItemType
                  ?? typeof(TResult).TryGetSequenceType();

            try
            {
                return((Func <QueryContext, TResult>)CompileAsyncQueryMethod
                       .MakeGenericMethod(resultItemType)
                       .Invoke(database, new object[] { queryModel }));
            }
            catch (TargetInvocationException e)
            {
                ExceptionDispatchInfo.Capture(e.InnerException).Throw();

                throw;
            }
        }
        private static Func <QueryContext, TResult> CompileQueryCore <TResult>(
            Expression query,
            IQueryModelGenerator queryModelGenerator,
            IDatabase database,
            IDiagnosticsLogger <DbLoggerCategory.Query> logger,
            Type contextType,
            bool getRealResult = false)
        {
            var queryModel = queryModelGenerator.ParseQuery(query);

            var resultItemType
                = (queryModel.GetOutputDataInfo()
                   as StreamedSequenceInfo)?.ResultItemType
                  ?? typeof(TResult);

            if (resultItemType == typeof(TResult))
            {
                var compiledQuery = database.CompileQuery <TResult>(queryModel);

                return(qc =>
                {
                    try
                    {
                        return compiledQuery(qc).First();
                    }
                    catch (Exception exception)
                    {
                        logger.QueryIterationFailed(contextType, exception);

                        throw;
                    }
                });
            }

            try
            {
                // differs from base implmentation to return DB query result
                var compileFunction = (Func <QueryContext, TResult>)CompileQueryMethod
                                      .MakeGenericMethod(resultItemType)
                                      .Invoke(database, new object[] { queryModel });

                return(qc =>
                {
                    try
                    {
                        // calling ToList to materialize result
                        var genericToListMethod = ToListMethod.MakeGenericMethod(new Type[] { resultItemType });
                        var result = genericToListMethod.Invoke(compileFunction(qc), new object[] { compileFunction(qc) });

                        return (TResult)result;
                    }
                    catch (Exception exception)
                    {
                        logger.QueryIterationFailed(contextType, exception);

                        throw;
                    }
                });
            }
            catch (TargetInvocationException e)
            {
                ExceptionDispatchInfo.Capture(e.InnerException).Throw();

                throw;
            }
        }