public virtual Func <QueryContext, TResult> CreateQueryExecutor <TResult>([NotNull] Expression query) { Check.NotNull(query, nameof(query)); query = _queryTranslationPreprocessorFactory.Create(this).Process(query); // Convert EntityQueryable to ShapedQueryExpression query = _queryableMethodTranslatingExpressionVisitorFactory.Create(Model).Visit(query); query = _queryTranslationPostprocessorFactory.Create(this).Process(query); // Inject actual entity materializer // Inject tracking query = _shapedQueryCompilingExpressionVisitorFactory.Create(this).Visit(query); // If any additional parameters were added during the compilation phase (e.g. entity equality ID expression), // wrap the query with code adding those parameters to the query context query = InsertRuntimeParameters(query); var queryExecutorExpression = Expression.Lambda <Func <QueryContext, TResult> >( query, QueryContextParameter); try { return(queryExecutorExpression.Compile()); } finally { Logger.QueryExecutionPlanned(new ExpressionPrinter(), queryExecutorExpression); } }
/// <summary> /// parse select statement of queryable /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="queryable"></param> /// <param name="ctx"></param> /// <returns></returns> public static SelectParsingResult Parse <TEntity>(this IQueryable <TEntity> queryable, DbContext ctx, bool ignoreQueryFilters) where TEntity : class { if (ignoreQueryFilters) { queryable = queryable.IgnoreQueryFilters(); } SelectParsingResult parsingResult = new SelectParsingResult(); Expression query = queryable.Expression; var databaseDependencies = ctx.GetService <DatabaseDependencies>(); IQueryTranslationPreprocessorFactory _queryTranslationPreprocessorFactory = ctx.GetService <IQueryTranslationPreprocessorFactory>(); IQueryableMethodTranslatingExpressionVisitorFactory _queryableMethodTranslatingExpressionVisitorFactory = ctx.GetService <IQueryableMethodTranslatingExpressionVisitorFactory>(); IQueryTranslationPostprocessorFactory _queryTranslationPostprocessorFactory = ctx.GetService <IQueryTranslationPostprocessorFactory>(); QueryCompilationContext queryCompilationContext = databaseDependencies.QueryCompilationContextFactory.Create(true); IDiagnosticsLogger <DbLoggerCategory.Query> logger = ctx.GetService <IDiagnosticsLogger <DbLoggerCategory.Query> >(); QueryContext queryContext = ctx.GetService <IQueryContextFactory>().Create(); QueryCompiler queryComipler = ctx.GetService <IQueryCompiler>() as QueryCompiler; //parameterize determines if it will use "Declare" or not MethodCallExpression methodCallExpr1 = queryComipler.ExtractParameters(query, queryContext, logger, parameterize: true) as MethodCallExpression; QueryTranslationPreprocessor queryTranslationPreprocessor = _queryTranslationPreprocessorFactory.Create(queryCompilationContext); MethodCallExpression methodCallExpr2 = queryTranslationPreprocessor.Process(methodCallExpr1) as MethodCallExpression; QueryableMethodTranslatingExpressionVisitor queryableMethodTranslatingExpressionVisitor = _queryableMethodTranslatingExpressionVisitorFactory.Create(queryCompilationContext); ShapedQueryExpression shapedQueryExpression1 = queryableMethodTranslatingExpressionVisitor.Visit(methodCallExpr2) as ShapedQueryExpression; QueryTranslationPostprocessor queryTranslationPostprocessor = _queryTranslationPostprocessorFactory.Create(queryCompilationContext); ShapedQueryExpression shapedQueryExpression2 = queryTranslationPostprocessor.Process(shapedQueryExpression1) as ShapedQueryExpression; IRelationalParameterBasedSqlProcessorFactory _relationalParameterBasedSqlProcessorFactory = ctx.GetService <IRelationalParameterBasedSqlProcessorFactory>(); RelationalParameterBasedSqlProcessor _relationalParameterBasedSqlProcessor = _relationalParameterBasedSqlProcessorFactory.Create(true); SelectExpression selectExpression = (SelectExpression)shapedQueryExpression2.QueryExpression; selectExpression = _relationalParameterBasedSqlProcessor.Optimize(selectExpression, queryContext.ParameterValues, out bool canCache); IQuerySqlGeneratorFactory querySqlGeneratorFactory = ctx.GetService <IQuerySqlGeneratorFactory>(); IZackQuerySqlGenerator querySqlGenerator = querySqlGeneratorFactory.Create() as IZackQuerySqlGenerator; if (querySqlGenerator == null) { throw new InvalidOperationException("please add dbContext.UseBatchEF() to OnConfiguring first!"); } querySqlGenerator.IsForBatchEF = true; querySqlGenerator.GetCommand(selectExpression); parsingResult.Parameters = queryContext.ParameterValues; parsingResult.PredicateSQL = querySqlGenerator.PredicateSQL; parsingResult.ProjectionSQL = querySqlGenerator.ProjectionSQL; TableExpression tableExpression = selectExpression.Tables[0] as TableExpression; parsingResult.TableName = tableExpression.Table.Name; return(parsingResult); }