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;
            }
        }
Example #2
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 virtual void Optimize(
            QueryCompilationContext queryCompilationContext,
            QueryModel queryModel)
        {
            _queryCompilationContext = queryCompilationContext;

            new AdditionalFromClauseOptimizingQueryModelVisitor(_queryCompilationContext).VisitQueryModel(queryModel);

            VisitQueryModel(queryModel);

            // second pass of TransparentIdentifier removal - this is temporary, until relinq is removed
            var tirev = new TransparentIdentifierRemovingVisitor();

            queryModel.TransformExpressions(tirev.Visit);

            queryModel.TransformExpressions(_transformingExpressionVisitor.Visit);
            queryModel.TransformExpressions(new ConditionalOptimizingExpressionVisitor().Visit);
            queryModel.TransformExpressions(new EntityEqualityRewritingExpressionVisitor(queryCompilationContext).Visit);
            queryModel.TransformExpressions(new SubQueryMemberPushDownExpressionVisitor(queryCompilationContext).Visit);
            queryModel.TransformExpressions(new ExistsToAnyRewritingExpressionVisitor().Visit);
            queryModel.TransformExpressions(new AllAnyToContainsRewritingExpressionVisitor().Visit);
        }
        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;
            }
        }