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; } }
/// <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; } }