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