private HashCodeCombiner GetExpressionHash(Expression expression) { var queryContext = _queryContextFactory.Create(); expression = _queryCompiler.ExtractParameters( expression, queryContext, _logger, parameterize: false); var hashCode = ExpressionEqualityComparer.Instance.GetHashCode(expression); var combiner = HashCodeCombiner.Start().Add(hashCode); var parameterValues = queryContext.ParameterValues; if (parameterValues.Count > 0) { // If query has parameters add to combiner foreach (var p in parameterValues) { combiner.Add(p.Key); combiner.Add(p.Value); } } return(combiner); }
/// <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); }
private static (string ExpressionKeyHash, Expression ModifiedExpression) getExpressionKeyHash( QueryCompiler queryCompiler, IEFCacheKeyHashProvider cacheKeyHashProvider, Expression expression) { var queryContextFactory = (IQueryContextFactory)_queryContextFactoryField.GetValue(queryCompiler); var queryContext = queryContextFactory.Create(); var logger = (IDiagnosticsLogger <DbLoggerCategory.Query>)_loggerField.GetValue(queryCompiler); expression = queryCompiler.ExtractParameters(expression, queryContext, logger, parameterize: false); 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), expression); }