/// <summary>
        /// Getting the SQL for a Query
        /// </summary>
        /// <param name="query">The query</param>
        /// <param name="expression">The expression tree</param>
        /// <param name="cacheKeyHashProvider">The CacheKey Hash Provider</param>
        public static EFToSqlData ToSql <TEntity>(
            this IQueryable <TEntity> query,
            Expression expression,
            IEFCacheKeyHashProvider cacheKeyHashProvider)
        {
            var queryCompiler    = (IQueryCompiler)_queryCompilerField.GetValue(query.Provider);
            var nodeTypeProvider = (INodeTypeProvider)_nodeTypeProviderField.GetValue(queryCompiler);
            var parser           = (IQueryParser)_createQueryParserMethod.Invoke(queryCompiler, new object[] { nodeTypeProvider });
            var queryModel       = parser.GetParsedQuery(expression);
            var database         = _dataBaseField.GetValue(queryCompiler);
            var queryCompilationContextFactory = (IQueryCompilationContextFactory)_queryCompilationContextFactoryField.GetValue(database);
            var queryCompilationContext        = queryCompilationContextFactory.Create(false);
            var modelVisitor = queryCompilationContext.CreateQueryModelVisitor();

            try
            {
                modelVisitor.CreateQueryExecutor <TEntity>(queryModel);
            }
            catch (ArgumentException)
            {
                // we don't care about its final casting and result.
            }

            if (!(modelVisitor is RelationalQueryModelVisitor relationalQueryModelVisitor))
            {
                return(new EFToSqlData(queryModel.ToString(), string.Empty));
            }

            var sql = relationalQueryModelVisitor.Queries.Join(Environment.NewLine);

            return(new EFToSqlData(sql, string.Empty));
        }
        private static string toSql(
            IQueryable query,
            Expression expression,
            IEFCacheKeyHashProvider cacheKeyHashProvider)
        {
            var queryCompiler    = (IQueryCompiler)_queryCompilerField.GetValue(query.Provider);
            var nodeTypeProvider = (INodeTypeProvider)_nodeTypeProviderField.GetValue(queryCompiler);
            var parser           = (IQueryParser)_createQueryParserMethod.Invoke(queryCompiler, new object[] { nodeTypeProvider });
            var queryModel       = parser.GetParsedQuery(expression);
            var database         = _dataBaseField.GetValue(queryCompiler);
            var queryCompilationContextFactory = (IQueryCompilationContextFactory)_queryCompilationContextFactoryField.GetValue(database);
            var queryCompilationContext        = queryCompilationContextFactory.Create(false);
            var modelVisitor = queryCompilationContext.CreateQueryModelVisitor();

            try
            {
                var createQueryExecutorMethod = modelVisitor.GetType().GetMethod("CreateQueryExecutor").MakeGenericMethod(query.ElementType);
                createQueryExecutorMethod.Invoke(modelVisitor, new object[] { queryModel });
            }
            catch (ArgumentException)
            {
                // we don't care about its final casting and result.
            }

            if (!(modelVisitor is RelationalQueryModelVisitor relationalQueryModelVisitor))
            {
                return(queryModel.ToString());
            }

            return(relationalQueryModelVisitor.Queries.Join(Environment.NewLine));
        }
        /// <summary>
        /// Getting the SQL for a Query
        /// </summary>
        /// <param name="query">The query</param>
        /// <param name="expression">The expression tree</param>
        /// <param name="cacheKeyHashProvider">The CacheKey Hash Provider</param>
        public static EFToSqlData ToSql <TEntity>(
            this IQueryable <TEntity> query,
            Expression expression,
            IEFCacheKeyHashProvider cacheKeyHashProvider)
        {
            var queryCompiler       = (IQueryCompiler)_queryCompilerField.GetValue(query.Provider);
            var queryModelGenerator = (IQueryModelGenerator)_queryModelGeneratorField.GetValue(queryCompiler);

            var expressionKeyHash = getExpressionKeyHash(queryCompiler, queryModelGenerator, cacheKeyHashProvider, expression);
            var cachedSql         = _keysCacheManager.Get <string>(expressionKeyHash);

            if (cachedSql != null)
            {
                return(new EFToSqlData(cachedSql, expressionKeyHash));
            }

            var nodeTypeProvider               = (INodeTypeProvider)_nodeTypeProviderField.GetValue(queryModelGenerator);
            var parser                         = (IQueryParser)_createQueryParserMethod.Invoke(queryModelGenerator, new object[] { nodeTypeProvider });
            var queryModel                     = parser.GetParsedQuery(expression);
            var database                       = _dataBaseField.GetValue(queryCompiler);
            var databaseDependencies           = (DatabaseDependencies)_databaseDependenciesProperty.GetValue(database);
            var queryCompilationContextFactory = databaseDependencies.QueryCompilationContextFactory;
            var queryCompilationContext        = queryCompilationContextFactory.Create(false);
            var modelVisitor                   = queryCompilationContext.CreateQueryModelVisitor();

            try
            {
                modelVisitor.CreateQueryExecutor <TEntity>(queryModel);
            }
            catch (ArgumentException)
            {
                // we don't care about its final casting and result.
            }

            if (!(modelVisitor is RelationalQueryModelVisitor relationalQueryModelVisitor))
            {
                var queryModelInfo = queryModel.ToString();
                setCache(expressionKeyHash, queryModelInfo);
                return(new EFToSqlData(queryModelInfo, expressionKeyHash));
            }

            var sql = relationalQueryModelVisitor.Queries.Join(Environment.NewLine);

            setCache(expressionKeyHash, sql);
            return(new EFToSqlData(sql, expressionKeyHash));
        }
        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));
        }
Beispiel #5
0
 /// <summary>
 /// A custom cache key provider for EF queries.
 /// </summary>
 /// <param name="cacheKeyHashProvider">Provides the custom hashing algorithm.</param>
 public EFCacheKeyProvider(IEFCacheKeyHashProvider cacheKeyHashProvider)
 {
     _cacheKeyHashProvider = cacheKeyHashProvider;
 }
Beispiel #6
0
 /// <summary>
 /// A custom cache key provider for normal LINQ to objects queries.
 /// </summary>
 /// <param name="cacheKeyHashProvider">Provides the custom hashing algorithm.</param>
 public LinqToObjectsCacheKeyProvider(IEFCacheKeyHashProvider cacheKeyHashProvider)
 {
     _cacheKeyHashProvider = cacheKeyHashProvider;
 }