/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual void Initialize([NotNull] RelationalQueryContext queryContext) { _queryContext = queryContext; _queryContext.BeginIncludeScope(); _relatedEntitiesLoaders = _relatedEntitiesLoaderFactories.Select(f => f(queryContext)) .ToArray(); _previous?.Initialize(queryContext); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual AsyncGroupJoinIncludeContext Initialize([NotNull] RelationalQueryContext queryContext) { var asyncGroupJoinIncludeContext = new AsyncGroupJoinIncludeContext( NavigationPath, QuerySourceRequiresTracking, queryContext, _relatedEntitiesLoaderFactories); if (_previous != null) { asyncGroupJoinIncludeContext.SetPrevious(_previous.Initialize(queryContext)); } return(asyncGroupJoinIncludeContext); }
public GroupJoinAsyncEnumerable( RelationalQueryContext queryContext, IAsyncEnumerable <ValueBuffer> source, IShaper <TOuter> outerShaper, IShaper <TInner> innerShaper, Func <TInner, TKey> innerKeySelector, Func <TOuter, IAsyncEnumerable <TInner>, TResult> resultSelector) { _queryContext = queryContext; _source = source; _outerShaper = outerShaper; _innerShaper = innerShaper; _innerKeySelector = innerKeySelector; _resultSelector = resultSelector; _hasOuters = (_innerShaper as EntityShaper)?.ValueBufferOffset > 0; }
/// <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 FromSqlQueryingEnumerable( [NotNull] RelationalQueryContext relationalQueryContext, [NotNull] RelationalCommandCache relationalCommandCache, [NotNull] IReadOnlyList <string> columnNames, [NotNull] Func <QueryContext, DbDataReader, int[], T> shaper, [NotNull] Type contextType, bool performIdentityResolution) { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; _columnNames = columnNames; _shaper = shaper; _contextType = contextType; _queryLogger = relationalQueryContext.QueryLogger; _performIdentityResolution = performIdentityResolution; }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual GroupJoinIncludeContext CreateIncludeContext([NotNull] RelationalQueryContext queryContext) { var groupJoinIncludeContext = new GroupJoinIncludeContext( _navigationPath, _querySourceRequiresTracking, queryContext, _relatedEntitiesLoaderFactories); if (_previous != null) { groupJoinIncludeContext.SetPrevious(_previous.CreateIncludeContext(queryContext)); } return(groupJoinIncludeContext); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public GroupJoinIncludeContext( [NotNull] IReadOnlyList <INavigation> navigationPath, bool querySourceRequiresTracking, [NotNull] RelationalQueryContext queryContext, [NotNull] IReadOnlyList <Func <QueryContext, IRelatedEntitiesLoader> > relatedEntitiesLoaderFactories) { _navigationPath = navigationPath; _querySourceRequiresTracking = querySourceRequiresTracking; _queryContext = queryContext; _queryContext.BeginIncludeScope(); _relatedEntitiesLoaders = relatedEntitiesLoaderFactories.Select(f => f(queryContext)) .ToArray(); }
/// <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 FromSqlQueryingEnumerable( [NotNull] RelationalQueryContext relationalQueryContext, [NotNull] RelationalCommandCache relationalCommandCache, [NotNull] IReadOnlyList <string> columnNames, [NotNull] Func <QueryContext, DbDataReader, int[], T> shaper, [NotNull] Type contextType, bool standAloneStateManager) { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; _columnNames = columnNames; _shaper = shaper; _contextType = contextType; _queryLogger = relationalQueryContext.QueryLogger; _standAloneStateManager = standAloneStateManager; }
/// <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 QueryingEnumerable( [NotNull] RelationalQueryContext relationalQueryContext, [NotNull] RelationalCommandCache relationalCommandCache, [NotNull] IReadOnlyList <string> columnNames, [NotNull] IReadOnlyList <ReaderColumn> readerColumns, [NotNull] Func <QueryContext, DbDataReader, ResultContext, int[], ResultCoordinator, T> shaper, [NotNull] Type contextType, [NotNull] IDiagnosticsLogger <DbLoggerCategory.Query> logger) { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; _columnNames = columnNames; _readerColumns = readerColumns; _shaper = shaper; _contextType = contextType; _logger = logger; }
internal static void PatchInExpressions(this SelectExpression expression, RelationalQueryContext context, List <string> usedParams = null) { if (context is null || expression is null) { return; } expression.Having.PatchInExpressions(context, usedParams); expression.Limit.PatchInExpressions(context, usedParams); expression.Offset.PatchInExpressions(context, usedParams); expression.Predicate.PatchInExpressions(context, usedParams); if (expression.Orderings != null) { foreach (var order in expression.Orderings) { order.Expression.PatchInExpressions(context, usedParams); } } if (expression.Projection != null) { foreach (var projection in expression.Projection) { projection.Expression.PatchInExpressions(context, usedParams); } } if (expression.Tables != null) { foreach (var table in expression.Tables) { table.PatchInExpressions(context, usedParams); } } if (expression.GroupBy != null) { foreach (var groupBy in expression.GroupBy) { groupBy.PatchInExpressions(context, usedParams); } } }
/// <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 SingleQueryingEnumerable( RelationalQueryContext relationalQueryContext, RelationalCommandCache relationalCommandCache, Func <QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator, T> shaper, Type contextType, bool standAloneStateManager, bool detailedErrorsEnabled, bool threadSafetyChecksEnabled) { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; _shaper = shaper; _contextType = contextType; _queryLogger = relationalQueryContext.QueryLogger; _standAloneStateManager = standAloneStateManager; _detailedErrorsEnabled = detailedErrorsEnabled; _threadSafetyChecksEnabled = threadSafetyChecksEnabled; }
public QueryingEnumerable(RelationalQueryContext relationalQueryContext, IQuerySqlGeneratorFactory querySqlGeneratorFactory, ISqlExpressionFactory sqlExpressionFactory, IParameterNameGeneratorFactory parameterNameGeneratorFactory, SelectExpression selectExpression, Func <QueryContext, DbDataReader, ResultCoordinator, T> shaper, Type contextType, IDiagnosticsLogger <DbLoggerCategory.Query> logger) { _relationalQueryContext = relationalQueryContext; _querySqlGeneratorFactory = querySqlGeneratorFactory; _sqlExpressionFactory = sqlExpressionFactory; _parameterNameGeneratorFactory = parameterNameGeneratorFactory; _selectExpression = selectExpression; _shaper = shaper; _contextType = contextType; _logger = logger; }
public SingleQueryingEnumerable( [NotNull] RelationalQueryContext relationalQueryContext, [NotNull] RelationalCommandCache relationalCommandCache, [NotNull] Func <QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator, T> shaper, [NotNull] Type contextType, bool standAloneStateManager, bool detailedErrorsEnabled, bool concurrencyDetectionEnabled) { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; _shaper = shaper; _contextType = contextType; _queryLogger = relationalQueryContext.QueryLogger; _standAloneStateManager = standAloneStateManager; _detailedErrorsEnabled = detailedErrorsEnabled; _concurrencyDetectionEnabled = concurrencyDetectionEnabled; }
/// <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 SplitQueryingEnumerable( [NotNull] RelationalQueryContext relationalQueryContext, [NotNull] RelationalCommandCache relationalCommandCache, [NotNull] Func <QueryContext, DbDataReader, ResultContext, SplitQueryResultCoordinator, T> shaper, [NotNull] Action <QueryContext, IExecutionStrategy, SplitQueryResultCoordinator> relatedDataLoaders, [NotNull] Func <QueryContext, IExecutionStrategy, SplitQueryResultCoordinator, Task> relatedDataLoadersAsync, [NotNull] Type contextType, bool standAloneStateManager) { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; _shaper = shaper; _relatedDataLoaders = relatedDataLoaders; _relatedDataLoadersAsync = relatedDataLoadersAsync; _contextType = contextType; _queryLogger = relationalQueryContext.QueryLogger; _standAloneStateManager = standAloneStateManager; }
public FromSqlNonComposedAsyncQueryingEnumerable( RelationalQueryContext relationalQueryContext, IQuerySqlGeneratorFactory2 querySqlGeneratorFactory, ISqlExpressionFactory sqlExpressionFactory, IParameterNameGeneratorFactory parameterNameGeneratorFactory, SelectExpression selectExpression, Func <QueryContext, DbDataReader, int[], Task <T> > shaper, Type contextType, IDiagnosticsLogger <DbLoggerCategory.Query> logger) { _relationalQueryContext = relationalQueryContext; _querySqlGeneratorFactory = querySqlGeneratorFactory; _sqlExpressionFactory = sqlExpressionFactory; _parameterNameGeneratorFactory = parameterNameGeneratorFactory; _selectExpression = selectExpression; _shaper = shaper; _contextType = contextType; _logger = logger; }
/// <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 FromSqlQueryingEnumerable( RelationalQueryContext relationalQueryContext, RelationalCommandCache relationalCommandCache, IReadOnlyList <string> columnNames, Func <QueryContext, DbDataReader, int[], T> shaper, Type contextType, bool standAloneStateManager, bool detailedErrorsEnabled, bool concurrencyDetectionEnabled) { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; _columnNames = columnNames; _shaper = shaper; _contextType = contextType; _queryLogger = relationalQueryContext.QueryLogger; _standAloneStateManager = standAloneStateManager; _detailedErrorsEnabled = detailedErrorsEnabled; _concurrencyDetectionEnabled = concurrencyDetectionEnabled; }
public static string GetConnectionStringForCacheKey(RelationalQueryContext queryContext) { var connection = queryContext.Connection.DbConnection; string connectionStringWithoutPassword = ""; // Remove the password from the connection string { if (connection.ConnectionString != null) { var list = new List <string>(); var keyValues = connection.ConnectionString.Split(';'); foreach (var keyValue in keyValues) { if (!string.IsNullOrEmpty(keyValue)) { var key = keyValue.Split('=')[0].Trim().ToLowerInvariant(); if (key != "password" && key != "pwd") { list.Add(keyValue); } } } connectionStringWithoutPassword = string.Join(",", list); } } // FORCE database name in case "ChangeDatabase()" method is used var connectionString = string.Concat(connection.DataSource ?? "", Environment.NewLine, connection.Database ?? "", Environment.NewLine, connectionStringWithoutPassword ?? ""); return(connectionString); }
/// <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 SplitQueryingEnumerable( RelationalQueryContext relationalQueryContext, RelationalCommandCache relationalCommandCache, Func <QueryContext, DbDataReader, ResultContext, SplitQueryResultCoordinator, T> shaper, Action <QueryContext, IExecutionStrategy, SplitQueryResultCoordinator> relatedDataLoaders, Func <QueryContext, IExecutionStrategy, SplitQueryResultCoordinator, Task> relatedDataLoadersAsync, Type contextType, bool standAloneStateManager, bool detailedErrorsEnabled, bool threadSafetyChecksEnabled) { _relationalQueryContext = relationalQueryContext; _relationalCommandCache = relationalCommandCache; _shaper = shaper; _relatedDataLoaders = relatedDataLoaders; _relatedDataLoadersAsync = relatedDataLoadersAsync; _contextType = contextType; _queryLogger = relationalQueryContext.QueryLogger; _standAloneStateManager = standAloneStateManager; _detailedErrorsEnabled = detailedErrorsEnabled; _threadSafetyChecksEnabled = threadSafetyChecksEnabled; }
/// <summary>Creates executor and get command.</summary> /// <returns>The new executor and get command.</returns> public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQueryContext queryContext) { var context = Query.GetDbContext(); // REFLECTION: Query._context.StateManager var stateManagerProperty = typeof(DbContext).GetProperty("StateManager", BindingFlags.NonPublic | BindingFlags.Instance); var stateManager = (StateManager)stateManagerProperty.GetValue(context); // REFLECTION: Query._context.StateManager._concurrencyDetector var concurrencyDetectorField = typeof(StateManager).GetField("_concurrencyDetector", BindingFlags.NonPublic | BindingFlags.Instance); var concurrencyDetector = (IConcurrencyDetector)concurrencyDetectorField.GetValue(stateManager); // REFLECTION: Query.Provider._queryCompiler var queryCompilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompiler = queryCompilerField.GetValue(Query.Provider); // REFLECTION: Query.Provider.NodeTypeProvider (Use property for nullable logic) var nodeTypeProviderField = queryCompiler.GetType().GetProperty("NodeTypeProvider", BindingFlags.NonPublic | BindingFlags.Instance); var nodeTypeProvider = nodeTypeProviderField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler.CreateQueryParser(); var createQueryParserMethod = queryCompiler.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Static); var createQueryParser = (QueryParser)createQueryParserMethod.Invoke(null, new[] { nodeTypeProvider }); // REFLECTION: Query.Provider._queryCompiler._database var databaseField = queryCompiler.GetType().GetField("_database", BindingFlags.NonPublic | BindingFlags.Instance); var database = (IDatabase)databaseField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler._evaluatableExpressionFilter var evaluatableExpressionFilterField = queryCompiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static); var evaluatableExpressionFilter = (IEvaluatableExpressionFilter)evaluatableExpressionFilterField.GetValue(null); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory var queryContextFactoryField = queryCompiler.GetType().GetField("_queryContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryContextFactory = (IQueryContextFactory)queryContextFactoryField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory.CreateQueryBuffer var createQueryBufferDelegateMethod = (typeof(QueryContextFactory)).GetMethod("CreateQueryBuffer", BindingFlags.NonPublic | BindingFlags.Instance); var createQueryBufferDelegate = (Func <IQueryBuffer>)createQueryBufferDelegateMethod.CreateDelegate(typeof(Func <IQueryBuffer>), queryContextFactory); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory._connection var connectionField = queryContextFactory.GetType().GetField("_connection", BindingFlags.NonPublic | BindingFlags.Instance); var connection = (IRelationalConnection)connectionField.GetValue(queryContextFactory); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory var queryCompilationContextFactoryField = typeof(Database).GetField("_queryCompilationContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(database); // CREATE connection QueryConnection = new CreateEntityRelationConnection(connection); // CREATE query context { var relationalQueryContextType = typeof(RelationalQueryContext); var relationalQueryContextConstructor = relationalQueryContextType.GetConstructors()[0]; // EF Core 1.1 preview if (relationalQueryContextConstructor.GetParameters().Length == 5) { // REFLECTION: Query.Provider._queryCompiler._queryContextFactory.ExecutionStrategyFactory var executionStrategyFactoryField = queryContextFactory.GetType().GetProperty("ExecutionStrategyFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); var executionStrategyFactory = executionStrategyFactoryField.GetValue(queryContextFactory); var lazyRefStateManager = new LazyRef <IStateManager>(() => stateManager); queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { createQueryBufferDelegate, QueryConnection, lazyRefStateManager, concurrencyDetector, executionStrategyFactory }); } else { queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { createQueryBufferDelegate, QueryConnection, stateManager, concurrencyDetector }); } } // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Logger var loggerField = queryCompilationContextFactory.GetType().GetProperty("Logger", BindingFlags.NonPublic | BindingFlags.Instance); var logger = (ISensitiveDataLogger)loggerField.GetValue(queryCompilationContextFactory); // CREATE new query from query visitor var newQuery = ParameterExtractingExpressionVisitor.ExtractParameters(Query.Expression, queryContext, evaluatableExpressionFilter, logger); // PARSE new query var queryModel = createQueryParser.GetParsedQuery(newQuery); // CREATE query model visitor var queryModelVisitor = (RelationalQueryModelVisitor)queryCompilationContextFactory.Create(false).CreateQueryModelVisitor(); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Create(false).CreateQueryModelVisitor().CreateQueryExecutor() var createQueryExecutorMethod = queryModelVisitor.GetType().GetMethod("CreateQueryExecutor"); var createQueryExecutorMethodGeneric = createQueryExecutorMethod.MakeGenericMethod(Query.ElementType); var queryExecutor = createQueryExecutorMethodGeneric.Invoke(queryModelVisitor, new[] { queryModel }); // SET value QueryExecutor = queryExecutor; QueryContext = queryContext; // RETURN the IRealationCommand var sqlQuery = queryModelVisitor.Queries.First(); var relationalCommand = sqlQuery.CreateDefaultQuerySqlGenerator().GenerateSql(queryContext.ParameterValues); return(relationalCommand); }
// Main implementation private static IEnumerable<T> FromCacheImplementation<T>(CachingMethod cachingMethod, IQueryable<T> query, out string cacheKey, CachingOptions options) where T : class { Logger.Log( "Performing " + cachingMethod + " for " + query.ToString() + " with options " + options.ToLog() + ".", LogLevel.Trace ); // Create NCache entry options CachingOptions optionsCloned = (CachingOptions)options.Clone(); cacheKey = null; string queryStoreKey = null; if (cachingMethod != CachingMethod.LoadIntoCache) { // Verify if query can be fetched seperately string pkCacheKey; if (QueryHelper.CanDirectPkFetch(query, optionsCloned, out pkCacheKey)) { object pkItem; if (QueryCacheManager.Cache.TryGetValue(pkCacheKey, out pkItem)) { List<T> resultSetPk = new List<T>(); List<T> resultSetPkTracked = new List<T>(); var stateManagerPk = query.GetStateManager(); resultSetPk.Add((T)pkItem); foreach (var entity in resultSetPk) { resultSetPkTracked.Add(((StateManager)stateManagerPk).GetRefValue(entity)); } return resultSetPkTracked; } } } bool cacheHit = false; IDictionary cacheResult = null; queryStoreKey = QueryCacheManager.GetQueryCacheKey(query, optionsCloned.QueryIdentifier); if (optionsCloned.StoreAs == StoreAs.Collection || optionsCloned.QueryIdentifier == null) { if (optionsCloned.StoreAs == StoreAs.Collection) cacheKey = queryStoreKey; if (optionsCloned.QueryIdentifier == null) optionsCloned.QueryIdentifier = queryStoreKey; } // Check in cache if (cachingMethod != CachingMethod.LoadIntoCache) { cacheHit = QueryCacheManager.Cache.GetByKey(queryStoreKey, out cacheResult); } // If not found in cache go for db if (!cacheHit) { var enumerableSet = query.AsEnumerable<T>(); CacheDependency dbDependency = null; if (optionsCloned.CreateDbDependency) { RelationalQueryContext queryContext = null; IRelationalCommand command = query.CreateCommand(out queryContext); string connectionString = queryContext.Connection.ConnectionString; dbDependency = GetDependency(NCacheConfiguration.DatabaseType, command.CommandText, connectionString); } return new NCacheEnumerable<T>(queryStoreKey, query, enumerableSet, optionsCloned, dbDependency); } // data is found in cache return result set else { // Assume its a collection if (cacheResult.Count == 1) { foreach (var item in cacheResult.Values) { CacheEntry entry = item as CacheEntry; if (entry != null) { // Confirmed stored as collection just return the value after casting IEnumerable<T> resultSetC = (IEnumerable<T>)entry.Value; // [Umer] i know this tracking is costly but there is no other solution var resultSetCTracked = new List<T>(); var stateManagerC = query.GetStateManager(); foreach (var entity in resultSetC) { resultSetCTracked.Add(((StateManager)stateManagerC).GetRefValue(entity)); } return resultSetCTracked; } break; } } var resultSetSE = cacheResult.Values.Cast<T>(); // [Umer] i know this tracking is costly but there is no other solution var resultSetSETracked = new List<T>(); var stateManagerSE = query.GetStateManager(); foreach (var entity in resultSetSE) { resultSetSETracked.Add(((StateManager)stateManagerSE).GetRefValue(entity)); } return resultSetSETracked; } }
public static IRelationalCommand CreateCommand <T>(this IQueryable <T> source, out RelationalQueryContext queryContext) { var compilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var compiler = compilerField.GetValue(source.Provider); // REFLECTION: Query.Provider.NodeTypeProvider (Use property for nullable logic) var nodeTypeProviderField = compiler.GetType().GetProperty("NodeTypeProvider", BindingFlags.NonPublic | BindingFlags.Instance); var nodeTypeProvider = nodeTypeProviderField.GetValue(compiler); var queryContextFactoryField = compiler.GetType().GetField("_queryContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryContextFactory = (IQueryContextFactory)queryContextFactoryField.GetValue(compiler); queryContext = (RelationalQueryContext)queryContextFactory.Create(); var evalutableExpressionFilterField = compiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static); var evalutableExpressionFilter = (IEvaluatableExpressionFilter)evalutableExpressionFilterField.GetValue(null); var databaseField = compiler.GetType().GetField("_database", BindingFlags.NonPublic | BindingFlags.Instance); var database = (IDatabase)databaseField.GetValue(compiler); // REFLECTION: Query.Provider._queryCompiler var queryCompilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompiler = queryCompilerField.GetValue(source.Provider); // REFLECTION: Query.Provider._queryCompiler._evaluatableExpressionFilter var evaluatableExpressionFilterField = queryCompiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static); var evaluatableExpressionFilter = (IEvaluatableExpressionFilter)evaluatableExpressionFilterField.GetValue(null); Expression newQuery; IQueryCompilationContextFactory queryCompilationContextFactory; var dependenciesProperty = typeof(Database).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); if (dependenciesProperty != null) { var dependencies = dependenciesProperty.GetValue(database); var queryCompilationContextFactoryField = typeof(DbContext).GetTypeFromAssembly_Core("Microsoft.EntityFrameworkCore.Storage.DatabaseDependencies") .GetProperty("QueryCompilationContextFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(dependencies); var dependenciesProperty2 = typeof(QueryCompilationContextFactory).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); var dependencies2 = dependenciesProperty2.GetValue(queryCompilationContextFactory); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Logger var loggerField = typeof(DbContext).GetTypeFromAssembly_Core("Microsoft.EntityFrameworkCore.Query.Internal.QueryCompilationContextDependencies") .GetProperty("Logger", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var logger = loggerField.GetValue(dependencies2); var parameterExtractingExpressionVisitorConstructor = typeof(ParameterExtractingExpressionVisitor).GetConstructors().First(x => x.GetParameters().Length == 5); var parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, logger, false, false }); // CREATE new query from query visitor newQuery = parameterExtractingExpressionVisitor.ExtractParameters(source.Expression); } else { // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory var queryCompilationContextFactoryField = typeof(Database).GetField("_queryCompilationContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(database); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Logger var loggerField = queryCompilationContextFactory.GetType().GetProperty("Logger", BindingFlags.NonPublic | BindingFlags.Instance); var logger = loggerField.GetValue(queryCompilationContextFactory); // CREATE new query from query visitor var extractParametersMethods = typeof(ParameterExtractingExpressionVisitor).GetMethod("ExtractParameters", BindingFlags.Public | BindingFlags.Static); newQuery = (Expression)extractParametersMethods.Invoke(null, new object[] { source.Expression, queryContext, evaluatableExpressionFilter, logger }); } //var query = new QueryAnnotatingExpressionVisitor().Visit(source.Expression); //var newQuery = ParameterExtractingExpressionVisitor.ExtractParameters(query, queryContext, evalutableExpressionFilter); var queryParserMethod = compiler.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Static); var queryparser = (QueryParser)queryParserMethod.Invoke(null, new [] { nodeTypeProvider }); var queryModel = queryparser.GetParsedQuery(newQuery); var queryModelVisitor = (RelationalQueryModelVisitor)queryCompilationContextFactory.Create(false).CreateQueryModelVisitor(); var executor = queryModelVisitor.CreateQueryExecutor <T>(queryModel); var queries = queryModelVisitor.Queries; var sqlQuery = queries.ToList()[0]; var command = sqlQuery.CreateDefaultQuerySqlGenerator().GenerateSql(queryContext.ParameterValues); return(command); }
internal static void PatchInExpressions(this InExpression expression, RelationalQueryContext context, List <string> usedParams = null) { if (context is null || expression is null) { return; } expression.Item.PatchInExpressions(context, usedParams); expression.Subquery?.PatchInExpressions(context, usedParams); if (expression.Values is null) { return; } // The version of VisitIn in EF Core 3.1.1 has two requirements. // 1) The Values must be from a SqlConstantExpression // 2) The Value from the SqlConstantExpression must be castable to IEnumerable<object> var currentValue = expression.Values; switch (currentValue) { case SqlParameterExpression paramEx: { // Fix issue 1 & 2 by grabbing the parameter and converting to a constant IEnumerable<object>. var value = context.ParameterValues[paramEx.Name]; if (usedParams != null && !usedParams.Contains(paramEx.Name)) { usedParams.Add(paramEx.Name); } var newVal = (value as IEnumerable)?.Cast <object>().ToArray() ?? new object[0]; var newEx = new SqlConstantExpression(Expression.Constant(newVal), paramEx.TypeMapping); if (!expression.SetNonPublicProperty("Values", newEx)) { throw new InvalidOperationException("Could not update Values for InExpression."); } break; } case SqlConstantExpression sqlConstEx: { // Fix issue 2, castable to IEnumerable<object> var constEx = sqlConstEx.GetNonPublicField <ConstantExpression>("_constantExpression"); var newVal = ((IEnumerable)constEx.Value).Cast <object>().ToArray(); var newEx = new SqlConstantExpression(Expression.Constant(newVal), sqlConstEx.TypeMapping); if (!expression.SetNonPublicProperty("Values", newEx)) { throw new InvalidOperationException("Could not update Values for InExpression."); } break; } default: throw new InvalidOperationException($"Don't know how to convert {currentValue.GetType()} to SqlConstantExpression."); } }
internal static void PatchInExpressions(this SqlExpression expression, RelationalQueryContext context, List <string> usedParams = null) { if (context is null || expression is null) { return; } switch (expression) { case InExpression inExpression: inExpression.PatchInExpressions(context, usedParams); break; case SqlUnaryExpression sqlUnaryExpression: sqlUnaryExpression.Operand.PatchInExpressions(context, usedParams); break; case CaseExpression caseExpression: foreach (var whenClause in caseExpression.WhenClauses) { whenClause.Result.PatchInExpressions(context, usedParams); whenClause.Test.PatchInExpressions(context, usedParams); } caseExpression.ElseResult.PatchInExpressions(context, usedParams); break; case ExistsExpression existsExpression: existsExpression.Subquery.PatchInExpressions(context, usedParams); break; case LikeExpression likeExpression: likeExpression.Match.PatchInExpressions(context, usedParams); likeExpression.Pattern.PatchInExpressions(context, usedParams); likeExpression.EscapeChar.PatchInExpressions(context, usedParams); break; case RowNumberExpression rowNumberExpression: if (rowNumberExpression.Orderings != null) { foreach (var order in rowNumberExpression.Orderings) { order.Expression.PatchInExpressions(context, usedParams); } } if (rowNumberExpression.Partitions != null) { foreach (var partition in rowNumberExpression.Partitions) { partition.PatchInExpressions(context, usedParams); } } break; case ScalarSubqueryExpression scalarSubqueryExpression: scalarSubqueryExpression.Subquery.PatchInExpressions(context, usedParams); break; case SqlBinaryExpression sqlBinaryExpression: sqlBinaryExpression.Left.PatchInExpressions(context, usedParams); sqlBinaryExpression.Right.PatchInExpressions(context, usedParams); break; case SqlFunctionExpression sqlFunctionExpression: if (sqlFunctionExpression.Arguments != null) { foreach (var argument in sqlFunctionExpression.Arguments) { argument.PatchInExpressions(context, usedParams); } } break; case SqlFragmentExpression _: case ColumnExpression _: case SqlConstantExpression _: case SqlParameterExpression _: break; default: throw new InvalidOperationException($"Unknown SQL expression type: {expression.GetType()}"); } }
/// <summary>Creates executor and get command.</summary> /// <returns>The new executor and get command.</returns> public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQueryContext queryContext) { queryContext = null; bool isEFCore2x = false; bool EFCore_2_1 = false; #if EFCORE bool isEFCore3x = EFCoreHelper.IsVersion3x; #endif var context = Query.GetDbContext(); // REFLECTION: Query._context.StateManager #if NETSTANDARD2_0 var stateManager = context.ChangeTracker.GetStateManager(); #else var stateManagerProperty = typeof(DbContext).GetProperty("StateManager", BindingFlags.NonPublic | BindingFlags.Instance); var stateManager = (StateManager)stateManagerProperty.GetValue(context); #endif // REFLECTION: Query._context.StateManager._concurrencyDetector var concurrencyDetectorField = typeof(StateManager).GetField("_concurrencyDetector", BindingFlags.NonPublic | BindingFlags.Instance); var concurrencyDetector = (IConcurrencyDetector)concurrencyDetectorField.GetValue(stateManager); // REFLECTION: Query.Provider._queryCompiler var queryCompilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompiler = queryCompilerField.GetValue(Query.Provider); // REFLECTION: Query.Provider.NodeTypeProvider (Use property for nullable logic) var nodeTypeProviderProperty = queryCompiler.GetType().GetProperty("NodeTypeProvider", BindingFlags.NonPublic | BindingFlags.Instance); object nodeTypeProvider; object QueryModelGenerator = null; if (nodeTypeProviderProperty == null) { EFCore_2_1 = true; var QueryModelGeneratorField = queryCompiler.GetType().GetField("_queryModelGenerator", BindingFlags.NonPublic | BindingFlags.Instance); QueryModelGenerator = QueryModelGeneratorField.GetValue(queryCompiler); var nodeTypeProviderField = QueryModelGenerator.GetType().GetField("_nodeTypeProvider", BindingFlags.NonPublic | BindingFlags.Instance); nodeTypeProvider = nodeTypeProviderField.GetValue(QueryModelGenerator); } else { nodeTypeProvider = nodeTypeProviderProperty.GetValue(queryCompiler); } // REFLECTION: Query.Provider._queryCompiler.CreateQueryParser(); #if NETSTANDARD2_0 QueryParser createQueryParser = null; if (EFCore_2_1) { var queryParserMethod = QueryModelGenerator.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Instance); createQueryParser = (QueryParser)queryParserMethod.Invoke(QueryModelGenerator, new[] { nodeTypeProvider }); } else { var queryParserMethod = queryCompiler.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Instance); createQueryParser = (QueryParser)queryParserMethod.Invoke(queryCompiler, new[] { nodeTypeProvider }); } #else var createQueryParserMethod = queryCompiler.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Static); var createQueryParser = (QueryParser)createQueryParserMethod.Invoke(null, new[] { nodeTypeProvider }); #endif // REFLECTION: Query.Provider._queryCompiler._database var databaseField = queryCompiler.GetType().GetField("_database", BindingFlags.NonPublic | BindingFlags.Instance); var database = (IDatabase)databaseField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler._evaluatableExpressionFilter #if NETSTANDARD2_0 IEvaluatableExpressionFilter evaluatableExpressionFilter = null; if (isEFCore3x) { evaluatableExpressionFilter = (RelationalEvaluatableExpressionFilter)QueryModelGenerator.GetType().GetProperty("EvaluatableExpressionFilter", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(QueryModelGenerator); } else if (EFCore_2_1) { evaluatableExpressionFilter = (IEvaluatableExpressionFilter)QueryModelGenerator.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(QueryModelGenerator); } else { evaluatableExpressionFilter = (IEvaluatableExpressionFilter)queryCompiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(queryCompiler); } #else var evaluatableExpressionFilterField = queryCompiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static); var evaluatableExpressionFilter = (IEvaluatableExpressionFilter)evaluatableExpressionFilterField.GetValue(null); #endif // REFLECTION: Query.Provider._queryCompiler._queryContextFactory var queryContextFactoryField = queryCompiler.GetType().GetField("_queryContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryContextFactory = (IQueryContextFactory)queryContextFactoryField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory.CreateQueryBuffer var createQueryBufferDelegateMethod = (typeof(QueryContextFactory)).GetMethod("CreateQueryBuffer", BindingFlags.NonPublic | BindingFlags.Instance); var createQueryBufferDelegate = (Func <IQueryBuffer>)createQueryBufferDelegateMethod.CreateDelegate(typeof(Func <IQueryBuffer>), queryContextFactory); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory._connection var connectionField = queryContextFactory.GetType().GetField("_connection", BindingFlags.NonPublic | BindingFlags.Instance); var connection = (IRelationalConnection)connectionField.GetValue(queryContextFactory); IQueryCompilationContextFactory queryCompilationContextFactory; object logger; var dependenciesProperty = typeof(Database).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); if (dependenciesProperty != null) { // EFCore 2.x isEFCore2x = true; var dependencies = dependenciesProperty.GetValue(database); var queryCompilationContextFactoryField = typeof(DbContext).GetTypeFromAssembly_Core("Microsoft.EntityFrameworkCore.Storage.DatabaseDependencies") .GetProperty("QueryCompilationContextFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(dependencies); var dependenciesProperty2 = typeof(QueryCompilationContextFactory).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); var dependencies2 = dependenciesProperty2.GetValue(queryCompilationContextFactory); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Logger var loggerField = typeof(DbContext).GetTypeFromAssembly_Core("Microsoft.EntityFrameworkCore.Query.Internal.QueryCompilationContextDependencies") .GetProperty("Logger", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); // (IInterceptingLogger<LoggerCategory.Query>) logger = loggerField.GetValue(dependencies2); } else { // EFCore 1.x // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory var queryCompilationContextFactoryField = typeof(Database).GetField("_queryCompilationContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(database); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Logger var loggerField = queryCompilationContextFactory.GetType().GetProperty("Logger", BindingFlags.NonPublic | BindingFlags.Instance); logger = loggerField.GetValue(queryCompilationContextFactory); } // CREATE connection { QueryConnection = context.Database.GetService <IRelationalConnection>(); var innerConnection = new CreateEntityConnection(QueryConnection.DbConnection, null); var innerConnectionField = typeof(RelationalConnection).GetField("_connection", BindingFlags.NonPublic | BindingFlags.Instance); var initalConnection = innerConnectionField.GetValue(QueryConnection); #if EFCORE_3X innerConnectionField.SetValue(QueryConnection, innerConnection); #else innerConnectionField.SetValue(QueryConnection, LazyHelper.NewLazy <DbConnection>(() => innerConnection)); #endif RestoreConnection = () => innerConnectionField.SetValue(QueryConnection, initalConnection); } // CREATE query context { var relationalQueryContextType = typeof(RelationalQueryContext); var relationalQueryContextConstructor = relationalQueryContextType.GetConstructors()[0]; // EF Core 1.1 preview if (isEFCore3x) { // REFLECTION: Query.Provider._queryCompiler._queryContextFactory.ExecutionStrategyFactory var executionStrategyFactoryField = queryContextFactory.GetType().GetProperty("ExecutionStrategyFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); var executionStrategyFactory = executionStrategyFactoryField.GetValue(queryContextFactory); var dependenciesProperty3 = typeof(RelationalQueryContextFactory).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); var dependencies3 = dependenciesProperty3.GetValue(queryContextFactory); queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { dependencies3, createQueryBufferDelegate, QueryConnection, executionStrategyFactory }); } else if (relationalQueryContextConstructor.GetParameters().Length == 5) { // REFLECTION: Query.Provider._queryCompiler._queryContextFactory.ExecutionStrategyFactory var executionStrategyFactoryField = queryContextFactory.GetType().GetProperty("ExecutionStrategyFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); var executionStrategyFactory = executionStrategyFactoryField.GetValue(queryContextFactory); #if !EFCORE_3X var lazyRefStateManager = LazyHelper.NewLazy(() => stateManager); queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { createQueryBufferDelegate, QueryConnection, lazyRefStateManager, concurrencyDetector, executionStrategyFactory }); #endif } else if (isEFCore2x) { // REFLECTION: Query.Provider._queryCompiler._queryContextFactory.ExecutionStrategyFactory var executionStrategyFactoryField = queryContextFactory.GetType().GetProperty("ExecutionStrategyFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); var executionStrategyFactory = executionStrategyFactoryField.GetValue(queryContextFactory); #if !EFCORE_3X var lazyRefStateManager = LazyHelper.NewLazy(() => stateManager); var dependenciesProperty3 = typeof(RelationalQueryContextFactory).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); var dependencies3 = dependenciesProperty3.GetValue(queryContextFactory); queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { dependencies3, createQueryBufferDelegate, QueryConnection, executionStrategyFactory }); #endif } else { queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { createQueryBufferDelegate, QueryConnection, stateManager, concurrencyDetector }); } } Expression newQuery = null; if (isEFCore3x) { #if EFCORE_3X var visitor = new ParameterExtractingExpressionVisitor(evaluatableExpressionFilter, queryContext, queryContext.GetType(), (IDiagnosticsLogger <DbLoggerCategory.Query>)logger, true, false); newQuery = visitor.ExtractParameters(Query.Expression); #endif //var parameterExtractingExpressionVisitorConstructor = typeof(ParameterExtractingExpressionVisitor).GetConstructors().First(x => x.GetParameters().Length == 6); //var parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, queryContext.GetType(), logger, true, false }); //// CREATE new query from query visitor //newQuery = parameterExtractingExpressionVisitor.ExtractParameters(Query.Expression); } else if (isEFCore2x) { var parameterExtractingExpressionVisitorConstructors = typeof(ParameterExtractingExpressionVisitor).GetConstructors(); if (parameterExtractingExpressionVisitorConstructors.Any(x => x.GetParameters().Length == 5)) { // EF Core 2.1 var parameterExtractingExpressionVisitorConstructor = parameterExtractingExpressionVisitorConstructors.First(x => x.GetParameters().Length == 5); var parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, logger, true, false }); // CREATE new query from query visitor newQuery = parameterExtractingExpressionVisitor.ExtractParameters(Query.Expression); } else { var parameterExtractingExpressionVisitorConstructor = parameterExtractingExpressionVisitorConstructors.First(x => x.GetParameters().Length == 6); ParameterExtractingExpressionVisitor parameterExtractingExpressionVisitor = null; if (parameterExtractingExpressionVisitorConstructor.GetParameters().Where(x => x.ParameterType == typeof(DbContext)).Any()) { parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, logger, context, true, false }); } else { parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, logger, null, true, false }); } // CREATE new query from query visitor newQuery = parameterExtractingExpressionVisitor.ExtractParameters(Query.Expression); } } else { // CREATE new query from query visitor var extractParametersMethods = typeof(ParameterExtractingExpressionVisitor).GetMethod("ExtractParameters", BindingFlags.Public | BindingFlags.Static); newQuery = (Expression)extractParametersMethods.Invoke(null, new object[] { Query.Expression, queryContext, evaluatableExpressionFilter, logger }); } // PARSE new query var queryModel = createQueryParser.GetParsedQuery(newQuery); // CREATE query model visitor var queryModelVisitor = (RelationalQueryModelVisitor)queryCompilationContextFactory.Create(false).CreateQueryModelVisitor(); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Create(false).CreateQueryModelVisitor().CreateQueryExecutor() var createQueryExecutorMethod = queryModelVisitor.GetType().GetMethod("CreateQueryExecutor"); var createQueryExecutorMethodGeneric = createQueryExecutorMethod.MakeGenericMethod(Query.ElementType); var queryExecutor = createQueryExecutorMethodGeneric.Invoke(queryModelVisitor, new[] { queryModel }); // SET value QueryExecutor = queryExecutor; QueryContext = queryContext; SelectExpression sqlQuery = null; if (queryModelVisitor.Queries.Count == 0) { var _subQueryModelVisitorsBySource = queryModelVisitor.GetType().GetField("_subQueryModelVisitorsBySource", BindingFlags.NonPublic | BindingFlags.Instance); var subQueryModelVisitorsBySources = (Dictionary <IQuerySource, RelationalQueryModelVisitor>)_subQueryModelVisitorsBySource.GetValue(queryModelVisitor); if (subQueryModelVisitorsBySources.Count == 1) { sqlQuery = subQueryModelVisitorsBySources.First().Value.Queries.First(); } else { throw new Exception("More than one query has been found inside the same query."); } } else { sqlQuery = queryModelVisitor.Queries.First(); } // RETURN the IRelationalCommand #if EFCORE IRelationalCommand relationalCommand = null; var dynamicSqlGenerator = (dynamic)sqlQuery.CreateDefaultQuerySqlGenerator(); if (isEFCore3x) { var commandBuilderFactory = context.Database.GetService <IRelationalCommandBuilderFactory>(); // TODO: Fix null for DbLogger relationalCommand = (IRelationalCommand)dynamicSqlGenerator.GenerateSql(commandBuilderFactory, queryContext.ParameterValues, null); } else { relationalCommand = (IRelationalCommand)dynamicSqlGenerator.GenerateSql(queryContext.ParameterValues); } #else var relationalCommand = sqlQuery.CreateDefaultQuerySqlGenerator().GenerateSql(queryContext.ParameterValues); #endif return(relationalCommand); }
//private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo(); //private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryCompiler"); //private static readonly FieldInfo QueryModelGeneratorField = QueryCompilerTypeInfo.DeclaredFields.First(x => x.Name == "_queryModelGenerator"); //private static readonly FieldInfo DataBaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database"); //private static readonly PropertyInfo DatabaseDependenciesField = typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies"); /// <summary>Creates executor and get command.</summary> /// <returns>The new executor and get command.</returns> public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQueryContext queryContext) { object compiledQueryOut; var relationalCommand = Query.EFPlusCreateCommand(queryable => { var context = queryable.GetDbContext(); QueryConnection = context.Database.GetService <IRelationalConnection>(); var innerConnection = new CreateEntityConnection(QueryConnection.DbConnection, null); var innerConnectionField = typeof(RelationalConnection).GetField("_connection", BindingFlags.NonPublic | BindingFlags.Instance); var initalConnection = innerConnectionField.GetValue(QueryConnection); innerConnectionField.SetValue(QueryConnection, innerConnection); RestoreConnection = () => innerConnectionField.SetValue(QueryConnection, initalConnection); }, out queryContext, out compiledQueryOut); QueryContext = queryContext; CompiledQuery = compiledQueryOut; return(relationalCommand); //var source = Query; //// CREATE connection //{ // var context = Query.GetDbContext(); // QueryConnection = context.Database.GetService<IRelationalConnection>(); // var innerConnection = new CreateEntityConnection(QueryConnection.DbConnection, null); // var innerConnectionField = typeof(RelationalConnection).GetField("_connection", BindingFlags.NonPublic | BindingFlags.Instance); // var initalConnection = innerConnectionField.GetValue(QueryConnection); // innerConnectionField.SetValue(QueryConnection, innerConnection); // RestoreConnection = () => innerConnectionField.SetValue(QueryConnection, initalConnection); //} //// REFLECTION: source.Provider._queryCompiler //var queryCompilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); //var queryCompiler = queryCompilerField.GetValue(source.Provider); //// REFLECTION: queryCompiler._database //var databaseField = queryCompiler.GetType().GetField("_database", BindingFlags.NonPublic | BindingFlags.Instance); //var database = (RelationalDatabase) databaseField.GetValue(queryCompiler); //// REFLECTION: queryCompiler._queryContextFactory().Create() //var queryContextFactoryField = queryCompiler.GetType().GetField("_queryContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); //var queryContextFactory = (IQueryContextFactory) queryContextFactoryField.GetValue(queryCompiler); //queryContext = (RelationalQueryContext) queryContextFactory.Create(); //// REFLECTION: queryCompiler._evaluatableExpressionFilter //var evaluatableExpressionFilterField = typeof(QueryCompiler).GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Instance); //var evaluatableExpressionFilter = (IEvaluatableExpressionFilter) evaluatableExpressionFilterField.GetValue(queryCompiler); //// REFLECTION: database.Dependencies //var dependenciesProperty = typeof(Database).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); //var dependencies = (DatabaseDependencies) dependenciesProperty.GetValue(database); //// queryCompilationContext //var queryCompilationContextFactory = dependencies.QueryCompilationContextFactory; //var queryCompilationContext = queryCompilationContextFactory.Create(false); //// parameterExtractingExpressionVisitor //var parameterExtractingExpressionVisitor = new ParameterExtractingExpressionVisitor(evaluatableExpressionFilter, queryContext, queryContext.GetType(), queryCompilationContext.Logger, true, false); //// CREATE new query from query visitor //var queryExpression = parameterExtractingExpressionVisitor.ExtractParameters(source.Expression); //// REFLECTION: database.CompileQuery<TResult>(queryExpression, false) //object compileQuery = null; //{ // // the code below somewhat replace the "CompileQuery" code like this: // // var queryingEnumerableType = database.GetType().Assembly.GetType("Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor+QueryingEnumerable`1").MakeGenericType(source.ElementType); // // var compileQueryMethod = database.GetType().GetMethod("CompileQuery", BindingFlags.Public | BindingFlags.Instance).MakeGenericMethod(queryingEnumerableType); // // compileQuery = compileQueryMethod.Invoke(database, new object[] { queryExpression, false }); // var query = queryExpression; // var queryCompilationFactory = (QueryCompilationContextFactory) dependencies.QueryCompilationContextFactory; // var queryCompilation = queryCompilationFactory.Create(false); // // get private stuff // var _queryOptimizerFactory = (IQueryOptimizerFactory)queryCompilation.GetType().GetField("_queryOptimizerFactory", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(queryCompilation); // var _queryableMethodTranslatingExpressionVisitorFactory = // (IQueryableMethodTranslatingExpressionVisitorFactory)queryCompilation.GetType().GetField("_queryableMethodTranslatingExpressionVisitorFactory", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(queryCompilation); // var _shapedQueryOptimizerFactory = (IShapedQueryOptimizerFactory)queryCompilation.GetType().GetField("_shapedQueryOptimizerFactory", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(queryCompilation); // var _shapedQueryCompilingExpressionVisitorFactory = (IShapedQueryCompilingExpressionVisitorFactory)queryCompilation.GetType().GetField("_shapedQueryCompilingExpressionVisitorFactory", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(queryCompilation); // var InsertRuntimeParametersMethod = queryCompilation.GetType().GetMethod("InsertRuntimeParameters", BindingFlags.NonPublic | BindingFlags.Instance); // query = _queryOptimizerFactory.Create(queryCompilation).Visit(query); // query = _queryableMethodTranslatingExpressionVisitorFactory.Create(queryCompilation.Model).Visit(query); // // required, otherwise the compileQuery return directly the result and not the command // { // var shapedQuery = (Microsoft.EntityFrameworkCore.Query.ShapedQueryExpression)query; // if (shapedQuery.ResultCardinality != ResultCardinality.Enumerable) // { // shapedQuery.ResultCardinality = ResultCardinality.Enumerable; // } // } // query = _shapedQueryOptimizerFactory.Create(queryCompilation).Visit(query); // query = _shapedQueryCompilingExpressionVisitorFactory.Create(queryCompilation).Visit(query); // query = (Expression) InsertRuntimeParametersMethod.Invoke(queryCompilation, new object[] {query}); // var method = typeof(BaseQueryFuture).GetMethod("SelfCompile", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(query.Type); // compileQuery = method.Invoke(null, new object[] {query, queryCompilation}); //} //var compiledQuery = ((dynamic) compileQuery)(queryContext); //// REFLECTION: compiledQuery._selectExpression //var selectExpressionField = ((Type) compiledQuery.GetType()).GetField("_selectExpression", BindingFlags.NonPublic | BindingFlags.Instance); //var selectExpression = (SelectExpression) selectExpressionField.GetValue(compiledQuery); //// REFLECTION: compiledQuery._querySqlGeneratorFactory //var querySqlGeneratorFactoryField = ((Type) compiledQuery.GetType()).GetField("_querySqlGeneratorFactory", BindingFlags.NonPublic | BindingFlags.Instance); //var querySqlGeneratorFactory = (IQuerySqlGeneratorFactory) querySqlGeneratorFactoryField.GetValue(compiledQuery); //var querySqlGenerator = querySqlGeneratorFactory.Create(); //var command = querySqlGenerator.GetCommand(selectExpression); //CompiledQuery = compiledQuery; //QueryContext = queryContext; //return command; }
/// <summary>Creates executor and get command.</summary> /// <returns>The new executor and get command.</returns> public virtual IRelationalCommand CreateExecutorAndGetCommand(out RelationalQueryContext queryContext) { bool isEFCore2x = false; var context = Query.GetDbContext(); // REFLECTION: Query._context.StateManager #if NETSTANDARD2_0 var stateManager = context.ChangeTracker.GetStateManager(); #else var stateManagerProperty = typeof(DbContext).GetProperty("StateManager", BindingFlags.NonPublic | BindingFlags.Instance); var stateManager = (StateManager)stateManagerProperty.GetValue(context); #endif // REFLECTION: Query._context.StateManager._concurrencyDetector var concurrencyDetectorField = typeof(StateManager).GetField("_concurrencyDetector", BindingFlags.NonPublic | BindingFlags.Instance); var concurrencyDetector = (IConcurrencyDetector)concurrencyDetectorField.GetValue(stateManager); // REFLECTION: Query.Provider._queryCompiler var queryCompilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompiler = queryCompilerField.GetValue(Query.Provider); // REFLECTION: Query.Provider.NodeTypeProvider (Use property for nullable logic) var nodeTypeProviderField = queryCompiler.GetType().GetProperty("NodeTypeProvider", BindingFlags.NonPublic | BindingFlags.Instance); var nodeTypeProvider = nodeTypeProviderField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler.CreateQueryParser(); #if NETSTANDARD2_0 var createQueryParserMethod = queryCompiler.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Instance); var createQueryParser = (QueryParser)createQueryParserMethod.Invoke(queryCompiler, new[] { nodeTypeProvider }); #else var createQueryParserMethod = queryCompiler.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Static); var createQueryParser = (QueryParser)createQueryParserMethod.Invoke(null, new[] { nodeTypeProvider }); #endif // REFLECTION: Query.Provider._queryCompiler._database var databaseField = queryCompiler.GetType().GetField("_database", BindingFlags.NonPublic | BindingFlags.Instance); var database = (IDatabase)databaseField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler._evaluatableExpressionFilter #if NETSTANDARD2_0 var evaluatableExpressionFilter = (IEvaluatableExpressionFilter)queryCompiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(queryCompiler); #else var evaluatableExpressionFilterField = queryCompiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static); var evaluatableExpressionFilter = (IEvaluatableExpressionFilter)evaluatableExpressionFilterField.GetValue(null); #endif // REFLECTION: Query.Provider._queryCompiler._queryContextFactory var queryContextFactoryField = queryCompiler.GetType().GetField("_queryContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryContextFactory = (IQueryContextFactory)queryContextFactoryField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory.CreateQueryBuffer var createQueryBufferDelegateMethod = (typeof(QueryContextFactory)).GetMethod("CreateQueryBuffer", BindingFlags.NonPublic | BindingFlags.Instance); var createQueryBufferDelegate = (Func <IQueryBuffer>)createQueryBufferDelegateMethod.CreateDelegate(typeof(Func <IQueryBuffer>), queryContextFactory); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory._connection var connectionField = queryContextFactory.GetType().GetField("_connection", BindingFlags.NonPublic | BindingFlags.Instance); var connection = (IRelationalConnection)connectionField.GetValue(queryContextFactory); IQueryCompilationContextFactory queryCompilationContextFactory; object logger; var dependenciesProperty = typeof(Database).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); if (dependenciesProperty != null) { // EFCore 2.x isEFCore2x = true; var dependencies = dependenciesProperty.GetValue(database); var queryCompilationContextFactoryField = typeof(DbContext).GetTypeFromAssembly_Core("Microsoft.EntityFrameworkCore.Storage.DatabaseDependencies") .GetProperty("QueryCompilationContextFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(dependencies); var dependenciesProperty2 = typeof(QueryCompilationContextFactory).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); var dependencies2 = dependenciesProperty2.GetValue(queryCompilationContextFactory); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Logger var loggerField = typeof(DbContext).GetTypeFromAssembly_Core("Microsoft.EntityFrameworkCore.Query.Internal.QueryCompilationContextDependencies") .GetProperty("Logger", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); // (IInterceptingLogger<LoggerCategory.Query>) logger = loggerField.GetValue(dependencies2); } else { // EFCore 1.x // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory var queryCompilationContextFactoryField = typeof(Database).GetField("_queryCompilationContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(database); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Logger var loggerField = queryCompilationContextFactory.GetType().GetProperty("Logger", BindingFlags.NonPublic | BindingFlags.Instance); logger = loggerField.GetValue(queryCompilationContextFactory); } // CREATE connection { QueryConnection = context.Database.GetService <IRelationalConnection>(); var innerConnection = new CreateEntityConnection(QueryConnection.DbConnection, null); var innerConnectionField = typeof(RelationalConnection).GetField("_connection", BindingFlags.NonPublic | BindingFlags.Instance); innerConnectionField.SetValue(QueryConnection, new Microsoft.EntityFrameworkCore.Internal.LazyRef <DbConnection>(() => innerConnection)); } // CREATE query context { var relationalQueryContextType = typeof(RelationalQueryContext); var relationalQueryContextConstructor = relationalQueryContextType.GetConstructors()[0]; // EF Core 1.1 preview if (relationalQueryContextConstructor.GetParameters().Length == 5) { // REFLECTION: Query.Provider._queryCompiler._queryContextFactory.ExecutionStrategyFactory var executionStrategyFactoryField = queryContextFactory.GetType().GetProperty("ExecutionStrategyFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); var executionStrategyFactory = executionStrategyFactoryField.GetValue(queryContextFactory); var lazyRefStateManager = new LazyRef <IStateManager>(() => stateManager); queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { createQueryBufferDelegate, QueryConnection, lazyRefStateManager, concurrencyDetector, executionStrategyFactory }); } else if (isEFCore2x) { // REFLECTION: Query.Provider._queryCompiler._queryContextFactory.ExecutionStrategyFactory var executionStrategyFactoryField = queryContextFactory.GetType().GetProperty("ExecutionStrategyFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); var executionStrategyFactory = executionStrategyFactoryField.GetValue(queryContextFactory); var lazyRefStateManager = new LazyRef <IStateManager>(() => stateManager); var dependenciesProperty3 = typeof(RelationalQueryContextFactory).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); var dependencies3 = dependenciesProperty3.GetValue(queryContextFactory); queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { dependencies3, createQueryBufferDelegate, QueryConnection, executionStrategyFactory }); } else { queryContext = (RelationalQueryContext)relationalQueryContextConstructor.Invoke(new object[] { createQueryBufferDelegate, QueryConnection, stateManager, concurrencyDetector }); } } Expression newQuery; if (isEFCore2x) { var parameterExtractingExpressionVisitorConstructor = typeof(ParameterExtractingExpressionVisitor).GetConstructors().First(x => x.GetParameters().Length == 5); var parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, logger, false, false }); // CREATE new query from query visitor newQuery = parameterExtractingExpressionVisitor.ExtractParameters(Query.Expression); } else { // CREATE new query from query visitor var extractParametersMethods = typeof(ParameterExtractingExpressionVisitor).GetMethod("ExtractParameters", BindingFlags.Public | BindingFlags.Static); newQuery = (Expression)extractParametersMethods.Invoke(null, new object[] { Query.Expression, queryContext, evaluatableExpressionFilter, logger }); } // PARSE new query var queryModel = createQueryParser.GetParsedQuery(newQuery); // CREATE query model visitor var queryModelVisitor = (RelationalQueryModelVisitor)queryCompilationContextFactory.Create(false).CreateQueryModelVisitor(); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Create(false).CreateQueryModelVisitor().CreateQueryExecutor() var createQueryExecutorMethod = queryModelVisitor.GetType().GetMethod("CreateQueryExecutor"); var createQueryExecutorMethodGeneric = createQueryExecutorMethod.MakeGenericMethod(Query.ElementType); var queryExecutor = createQueryExecutorMethodGeneric.Invoke(queryModelVisitor, new[] { queryModel }); // SET value QueryExecutor = queryExecutor; QueryContext = queryContext; // RETURN the IRealationCommand var sqlQuery = queryModelVisitor.Queries.First(); var relationalCommand = sqlQuery.CreateDefaultQuerySqlGenerator().GenerateSql(queryContext.ParameterValues); return(relationalCommand); }
/// <summary>Gets cached keys used to cache or retrieve a query from the QueryCacheManager.</summary> /// <param name="query">The query to cache or retrieve from the QueryCacheManager.</param> /// <param name="tags">A variable-length parameters list containing tags to create the cache key.</param> /// <returns>The cache key used to cache or retrieve a query from the QueryCacheManager.</returns> public static string GetCacheKey(IQueryable query, string[] tags) { if (CacheKeyFactory != null) { var cacheKey = CacheKeyFactory(query, tags); if (!string.IsNullOrEmpty(cacheKey)) { return(cacheKey); } } var sb = new StringBuilder(); #if EF5 || EF6 var queryCacheUniqueKeyMethod = query.GetType().GetMethod("GetQueryCacheUniqueKey", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (queryCacheUniqueKeyMethod != null) { var queryCacheUniqueKey = (string)queryCacheUniqueKeyMethod.Invoke(query, new object[] { tags }); if (!string.IsNullOrEmpty(queryCacheUniqueKey)) { return(queryCacheUniqueKey); } } if (IsCommandInfoOptionalForCacheKey && !UseFirstTagAsCacheKey && !UseTagsAsCacheKey) { throw new Exception(ExceptionMessage.QueryCache_IsCommandInfoOptionalForCacheKey_Invalid); } var objectQuery = IsCommandInfoOptionalForCacheKey ? query.GetObjectQuerySafe() : query.GetObjectQuery(); sb.AppendLine(CachePrefix); if (IncludeConnectionInCacheKey && objectQuery != null) { sb.AppendLine(GetConnectionStringForCacheKey(query)); } #elif EFCORE RelationalQueryContext queryContext = null; var command = query.CreateCommand(out queryContext); sb.AppendLine(CachePrefix); if (IncludeConnectionInCacheKey) { sb.AppendLine(GetConnectionStringForCacheKey(queryContext)); } #endif if (UseFirstTagAsCacheKey) { if (tags == null || tags.Length == 0 || string.IsNullOrEmpty(tags[0])) { throw new Exception(ExceptionMessage.QueryCache_FirstTagNullOrEmpty); } sb.AppendLine(tags[0]); return(sb.ToString()); } if (UseTagsAsCacheKey) { if (tags == null || tags.Length == 0 || tags.Any(string.IsNullOrEmpty)) { throw new Exception(ExceptionMessage.QueryCache_UseTagsNullOrEmpty); } sb.AppendLine(string.Join(";", tags)); return(sb.ToString()); } sb.AppendLine(string.Join(";", tags)); #if EF5 if (objectQuery != null) { sb.AppendLine(objectQuery.ToTraceString()); foreach (var parameter in objectQuery.Parameters) { sb.Append(parameter.Name); sb.Append(";"); sb.Append(parameter.Value); sb.AppendLine(";"); } } #elif EF6 if (objectQuery != null) { var commandTextAndParameters = objectQuery.GetCommandTextAndParameters(); sb.AppendLine(commandTextAndParameters.Item1); foreach (DbParameter parameter in commandTextAndParameters.Item2) { sb.Append(parameter.ParameterName); sb.Append(";"); sb.Append(parameter.Value); sb.AppendLine(";"); } } #elif EFCORE sb.AppendLine(query.Expression.ToString()); sb.AppendLine(command.CommandText); foreach (var parameter in queryContext.ParameterValues) { sb.Append(parameter.Key); sb.Append(";"); sb.Append(parameter.Value); sb.AppendLine(";"); } #endif return(sb.ToString()); }
/// <summary>Gets cached keys used to cache or retrieve a query from the QueryCacheManager.</summary> /// <param name="query">The query to cache or retrieve from the QueryCacheManager.</param> /// <param name="tags">A variable-length parameters list containing tags to create the cache key.</param> /// <returns>The cache key used to cache or retrieve a query from the QueryCacheManager.</returns> internal static string GetQueryCacheKey(IQueryable query, string tag) { if (tag != null) { UseFirstTagAsCacheKey = true; } if (CacheKeyFactory != null) { var cacheKey = CacheKeyFactory(query, new string[] { tag }); if (!string.IsNullOrEmpty(cacheKey)) { return(cacheKey); } } var sb = new StringBuilder(); #if EF5 || EF6 var queryCacheUniqueKeyMethod = query.GetType().GetMethod("GetQueryCacheUniqueKey", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (queryCacheUniqueKeyMethod != null) { var queryCacheUniqueKey = (string)queryCacheUniqueKeyMethod.Invoke(query, new object[] { tags }); if (!string.IsNullOrEmpty(queryCacheUniqueKey)) { return(queryCacheUniqueKey); } } if (IsCommandInfoOptionalForCacheKey && !UseFirstTagAsCacheKey && !UseTagsAsCacheKey) { throw new Exception(ExceptionMessage.QueryCache_IsCommandInfoOptionalForCacheKey_Invalid); } var objectQuery = IsCommandInfoOptionalForCacheKey ? query.GetObjectQuerySafe() : query.GetObjectQuery(); sb.AppendLine(CachePrefix); if (IncludeConnectionInCacheKey && objectQuery != null) { sb.AppendLine(GetConnectionStringForCacheKey(query)); } #elif EFCORE RelationalQueryContext queryContext = null; var command = query.CreateCommand(out queryContext); sb.Append(CachePrefix); if (IncludeConnectionInCacheKey) { sb.Append(GetConnectionStringForCacheKey(queryContext)); } if (!IncludeConnectionInCacheKey && IncludeUserNameAndDatabase) { sb.Append(GetUserNameAndDatabaseForCacheKey(queryContext)); sb.Append(';'); } #endif if (UseFirstTagAsCacheKey) { if (string.IsNullOrEmpty(tag)) { throw new Exception(ExceptionMessage.QueryCache_FirstTagNullOrEmpty); } UseFirstTagAsCacheKey = false; sb.Append("$QId$" + tag); return(sb.ToString()); } #if EF5 if (objectQuery != null) { sb.AppendLine(objectQuery.ToTraceString()); foreach (var parameter in objectQuery.Parameters) { sb.Append(parameter.Name); sb.Append(";"); sb.Append(parameter.Value); sb.AppendLine(";"); } } #elif EF6 if (objectQuery != null) { var commandTextAndParameters = objectQuery.GetCommandTextAndParameters(); sb.AppendLine(commandTextAndParameters.Item1); foreach (DbParameter parameter in commandTextAndParameters.Item2) { sb.Append(parameter.ParameterName); sb.Append(";"); sb.Append(parameter.Value); sb.AppendLine(";"); } } #elif EFCORE sb.Append(ExtensionMethods.ToStringWithoutAlias(query.Expression)); foreach (var parameter in queryContext.ParameterValues) { sb.Append(parameter.Key); sb.Append(","); sb.Append(parameter.Value); sb.AppendLine(";"); } #endif return(sb.ToString()); }
public static IRelationalCommand CreateCommand <T>(this IQueryable <T> source, out RelationalQueryContext queryContext) { var compilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var compiler = compilerField.GetValue(source.Provider); // REFLECTION: Query.Provider.NodeTypeProvider (Use property for nullable logic) var nodeTypeProviderField = compiler.GetType().GetProperty("NodeTypeProvider", BindingFlags.NonPublic | BindingFlags.Instance); var nodeTypeProvider = nodeTypeProviderField.GetValue(compiler); var queryContextFactoryField = compiler.GetType().GetField("_queryContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryContextFactory = (IQueryContextFactory)queryContextFactoryField.GetValue(compiler); queryContext = (RelationalQueryContext)queryContextFactory.Create(); var evalutableExpressionFilterField = compiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static); var evalutableExpressionFilter = (IEvaluatableExpressionFilter)evalutableExpressionFilterField.GetValue(null); var databaseField = compiler.GetType().GetField("_database", BindingFlags.NonPublic | BindingFlags.Instance); var database = (IDatabase)databaseField.GetValue(compiler); // REFLECTION: Query.Provider._queryCompiler var queryCompilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompiler = queryCompilerField.GetValue(source.Provider); // REFLECTION: Query.Provider._queryCompiler._evaluatableExpressionFilter var evaluatableExpressionFilterField = queryCompiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static); var evaluatableExpressionFilter = (IEvaluatableExpressionFilter)evaluatableExpressionFilterField.GetValue(null); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory var queryCompilationContextFactoryField = typeof(Database).GetField("_queryCompilationContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(database); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Logger var loggerField = queryCompilationContextFactory.GetType().GetProperty("Logger", BindingFlags.NonPublic | BindingFlags.Instance); var logger = (ISensitiveDataLogger)loggerField.GetValue(queryCompilationContextFactory); // CREATE new query from query visitor var newQuery = ParameterExtractingExpressionVisitor.ExtractParameters(source.Expression, queryContext, evaluatableExpressionFilter, logger); //var query = new QueryAnnotatingExpressionVisitor().Visit(source.Expression); //var newQuery = ParameterExtractingExpressionVisitor.ExtractParameters(query, queryContext, evalutableExpressionFilter); var queryParserMethod = compiler.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Static); var queryparser = (QueryParser)queryParserMethod.Invoke(null, new [] { nodeTypeProvider }); var queryModel = queryparser.GetParsedQuery(newQuery); var queryModelVisitor = (RelationalQueryModelVisitor)queryCompilationContextFactory.Create(false).CreateQueryModelVisitor(); var executor = queryModelVisitor.CreateQueryExecutor <T>(queryModel); var queries = queryModelVisitor.Queries; var sqlQuery = queries.ToList()[0]; var command = sqlQuery.CreateDefaultQuerySqlGenerator().GenerateSql(queryContext.ParameterValues); return(command); }
/// <summary>Creates executor and get command.</summary> /// <returns>The new executor and get command.</returns> public virtual IRelationalCommand CreateExecutorAndGetCommand() { // REFLECTION: Query.Provider._queryCompiler var queryCompilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompiler = queryCompilerField.GetValue(Query.Provider); // REFLECTION: Query.Provider._queryCompiler.CreateQueryParser(); var createQueryParserMethod = queryCompiler.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Static); var createQueryParser = (QueryParser)createQueryParserMethod.Invoke(null, new object[0]); // REFLECTION: Query.Provider._queryCompiler._database var databaseField = queryCompiler.GetType().GetField("_database", BindingFlags.NonPublic | BindingFlags.Instance); var database = (IDatabase)databaseField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler._evaluatableExpressionFilter var evaluatableExpressionFilterField = queryCompiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static); var evaluatableExpressionFilter = (IEvaluatableExpressionFilter)evaluatableExpressionFilterField.GetValue(null); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory var queryContextFactoryField = queryCompiler.GetType().GetField("_queryContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryContextFactory = (IQueryContextFactory)queryContextFactoryField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory.CreateQueryBuffer var createQueryBufferDelegateMethod = (typeof(QueryContextFactory)).GetMethod("CreateQueryBuffer", BindingFlags.NonPublic | BindingFlags.Instance); var createQueryBufferDelegate = (Func <IQueryBuffer>)createQueryBufferDelegateMethod.CreateDelegate(typeof(Func <IQueryBuffer>), queryContextFactory); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory._connection var connectionField = queryContextFactory.GetType().GetField("_connection", BindingFlags.NonPublic | BindingFlags.Instance); var connection = (IRelationalConnection)connectionField.GetValue(queryContextFactory); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory var queryCompilationContextFactoryField = typeof(Database).GetField("_queryCompilationContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(database); // CREATE connection QueryConnection = new CreateEntityRelationConnection(connection); // CREATE query context var queryContext = new RelationalQueryContext(createQueryBufferDelegate, QueryConnection); // CREATE a query visitor var queryVisitor = new QueryAnnotatingExpressionVisitor().Visit(Query.Expression); // CREATE new query from query visitor var newQuery = ParameterExtractingExpressionVisitor.ExtractParameters(queryVisitor, queryContext, evaluatableExpressionFilter); // PARSE new query var queryModel = createQueryParser.GetParsedQuery(newQuery); // CREATE query model visitor var queryModelVisitor = (RelationalQueryModelVisitor)queryCompilationContextFactory.Create(false).CreateQueryModelVisitor(); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Create(false).CreateQueryModelVisitor().CreateQueryExecutor() var createQueryExecutorMethod = queryModelVisitor.GetType().GetMethod("CreateQueryExecutor"); var createQueryExecutorMethodGeneric = createQueryExecutorMethod.MakeGenericMethod(Query.ElementType); var queryExecutor = createQueryExecutorMethodGeneric.Invoke(queryModelVisitor, new[] { queryModel }); // SET value QueryExecutor = queryExecutor; QueryContext = queryContext; // RETURN the IRealationCommand var sqlQuery = queryModelVisitor.Queries.First(); var relationalCommand = sqlQuery.CreateGenerator().GenerateSql(queryContext.ParameterValues); return(relationalCommand); }
public static IRelationalCommand CreateCommand(this IQueryable source, out RelationalQueryContext queryContext) { bool EFCore_2_1 = false; #if EFCORE bool isEFCore3x = EFCoreHelper.IsVersion3x; #endif var compilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var compiler = compilerField.GetValue(source.Provider); // REFLECTION: Query.Provider.NodeTypeProvider (Use property for nullable logic) var nodeTypeProviderProperty = compiler.GetType().GetProperty("NodeTypeProvider", BindingFlags.NonPublic | BindingFlags.Instance); object nodeTypeProvider; object QueryModelGenerator = null; if (nodeTypeProviderProperty == null) { EFCore_2_1 = true; var QueryModelGeneratorField = compiler.GetType().GetField("_queryModelGenerator", BindingFlags.NonPublic | BindingFlags.Instance); QueryModelGenerator = QueryModelGeneratorField.GetValue(compiler); var nodeTypeProviderField = QueryModelGenerator.GetType().GetField("_nodeTypeProvider", BindingFlags.NonPublic | BindingFlags.Instance); nodeTypeProvider = nodeTypeProviderField.GetValue(QueryModelGenerator); } else { nodeTypeProvider = nodeTypeProviderProperty.GetValue(compiler); } var queryContextFactoryField = compiler.GetType().GetField("_queryContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryContextFactory = (IQueryContextFactory)queryContextFactoryField.GetValue(compiler); queryContext = (RelationalQueryContext)queryContextFactory.Create(); var databaseField = compiler.GetType().GetField("_database", BindingFlags.NonPublic | BindingFlags.Instance); var database = (IDatabase)databaseField.GetValue(compiler); // REFLECTION: Query.Provider._queryCompiler var queryCompilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompiler = queryCompilerField.GetValue(source.Provider); // REFLECTION: Query.Provider._queryCompiler._evaluatableExpressionFilter #if NETSTANDARD2_0 IEvaluatableExpressionFilter evaluatableExpressionFilter = null; if (isEFCore3x) { evaluatableExpressionFilter = (RelationalEvaluatableExpressionFilter)QueryModelGenerator.GetType().GetProperty("EvaluatableExpressionFilter", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(QueryModelGenerator); } else if (EFCore_2_1) { evaluatableExpressionFilter = (IEvaluatableExpressionFilter)QueryModelGenerator.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(QueryModelGenerator); } else { evaluatableExpressionFilter = (IEvaluatableExpressionFilter)compiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(queryCompiler); } #else var evalutableExpressionFilterField = compiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static); var evalutableExpressionFilter = (IEvaluatableExpressionFilter)evalutableExpressionFilterField.GetValue(null); var evaluatableExpressionFilterField = queryCompiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static); var evaluatableExpressionFilter = (IEvaluatableExpressionFilter)evaluatableExpressionFilterField.GetValue(null); #endif Expression newQuery; IQueryCompilationContextFactory queryCompilationContextFactory; var dependenciesProperty = typeof(Database).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); if (dependenciesProperty != null) { var dependencies = dependenciesProperty.GetValue(database); var queryCompilationContextFactoryField = typeof(DbContext).GetTypeFromAssembly_Core("Microsoft.EntityFrameworkCore.Storage.DatabaseDependencies") .GetProperty("QueryCompilationContextFactory", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(dependencies); var dependenciesProperty2 = typeof(QueryCompilationContextFactory).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance); var dependencies2 = dependenciesProperty2.GetValue(queryCompilationContextFactory); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Logger var loggerField = typeof(DbContext).GetTypeFromAssembly_Core("Microsoft.EntityFrameworkCore.Query.Internal.QueryCompilationContextDependencies") .GetProperty("Logger", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var logger = loggerField.GetValue(dependencies2); var parameterExtractingExpressionVisitorConstructors = typeof(ParameterExtractingExpressionVisitor).GetConstructors(); if (isEFCore3x) { var parameterExtractingExpressionVisitorConstructor = typeof(ParameterExtractingExpressionVisitor).GetConstructors().First(x => x.GetParameters().Length == 6); var parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, queryContext.GetType(), logger, true, false }); // CREATE new query from query visitor newQuery = parameterExtractingExpressionVisitor.ExtractParameters(source.Expression); } else if (parameterExtractingExpressionVisitorConstructors.Any(x => x.GetParameters().Length == 5)) { // EF Core 2.1 var parameterExtractingExpressionVisitorConstructor = parameterExtractingExpressionVisitorConstructors.First(x => x.GetParameters().Length == 5); var parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, logger, true, false }); // CREATE new query from query visitor newQuery = parameterExtractingExpressionVisitor.ExtractParameters(source.Expression); } else { // EF Core 2.1 Preview 2. var parameterExtractingExpressionVisitorConstructor = parameterExtractingExpressionVisitorConstructors.First(x => x.GetParameters().Length == 6); var _context = queryContext.GetType().GetProperty("Context", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy); var context = _context.GetValue(queryContext); ParameterExtractingExpressionVisitor parameterExtractingExpressionVisitor = null; if (parameterExtractingExpressionVisitorConstructor.GetParameters().Where(x => x.ParameterType == typeof(DbContext)).Any()) { parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, logger, context, true, false }); } else { parameterExtractingExpressionVisitor = (ParameterExtractingExpressionVisitor)parameterExtractingExpressionVisitorConstructor.Invoke(new object[] { evaluatableExpressionFilter, queryContext, logger, null, true, false }); } // CREATE new query from query visitor newQuery = parameterExtractingExpressionVisitor.ExtractParameters(source.Expression); } } else { // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory var queryCompilationContextFactoryField = typeof(Database).GetField("_queryCompilationContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(database); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Logger var loggerField = queryCompilationContextFactory.GetType().GetProperty("Logger", BindingFlags.NonPublic | BindingFlags.Instance); var logger = loggerField.GetValue(queryCompilationContextFactory); // CREATE new query from query visitor var extractParametersMethods = typeof(ParameterExtractingExpressionVisitor).GetMethod("ExtractParameters", BindingFlags.Public | BindingFlags.Static); newQuery = (Expression)extractParametersMethods.Invoke(null, new object[] { source.Expression, queryContext, evaluatableExpressionFilter, logger }); //ParameterExtractingExpressionVisitor.ExtractParameters(source.Expression, queryContext, evaluatableExpressionFilter, logger); } //var query = new QueryAnnotatingExpressionVisitor().Visit(source.Expression); //var newQuery = ParameterExtractingExpressionVisitor.ExtractParameters(query, queryContext, evalutableExpressionFilter); #if NETSTANDARD2_0 QueryParser queryparser = null; if (EFCore_2_1) { var queryParserMethod = QueryModelGenerator.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Instance); queryparser = (QueryParser)queryParserMethod.Invoke(QueryModelGenerator, new[] { nodeTypeProvider }); } else { var queryParserMethod = compiler.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Instance); queryparser = (QueryParser)queryParserMethod.Invoke(compiler, new[] { nodeTypeProvider }); } #else var queryParserMethod = compiler.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Static); var queryparser = (QueryParser)queryParserMethod.Invoke(null, new[] { nodeTypeProvider }); #endif var queryModel = queryparser.GetParsedQuery(newQuery); var queryModelVisitor = (RelationalQueryModelVisitor)queryCompilationContextFactory.Create(false).CreateQueryModelVisitor(); var createQueryExecutorMethod = queryModelVisitor.GetType().GetMethod("CreateQueryExecutor"); var createQueryExecutorMethodGeneric = createQueryExecutorMethod.MakeGenericMethod(source.ElementType); createQueryExecutorMethodGeneric.Invoke(queryModelVisitor, new[] { queryModel }); var queries = queryModelVisitor.Queries; var sqlQuery = queries.ToList()[0]; IRelationalCommand relationalCommand = null; var dynamicSqlGenerator = (dynamic)sqlQuery.CreateDefaultQuerySqlGenerator(); if (isEFCore3x) { var commandBuilderFactory = queryContext.Context.Database.GetService <IRelationalCommandBuilderFactory>(); // TODO: Fix null for DbLogger relationalCommand = (IRelationalCommand)dynamicSqlGenerator.GenerateSql(commandBuilderFactory, queryContext.ParameterValues, null); } else { relationalCommand = (IRelationalCommand)dynamicSqlGenerator.GenerateSql(queryContext.ParameterValues); } return(relationalCommand); }
internal static IEnumerable <T> MapReader <T>(this DbContext context, DbDataReader reader) where T : class { #if EF5 || EF6 return(((IObjectContextAdapter)context).ObjectContext.Translate <T>(reader)); #elif EFCORE var list = new List <T>(); var query = (IQueryable <T>)context.Set <T>(); // REFLECTION: Query._context.StateManager var stateManagerProperty = typeof(DbContext).GetProperty("StateManager", BindingFlags.NonPublic | BindingFlags.Instance); var stateManager = (StateManager)stateManagerProperty.GetValue(context); // REFLECTION: Query._context.StateManager._concurrencyDetector var concurrencyDetectorField = typeof(StateManager).GetField("_concurrencyDetector", BindingFlags.NonPublic | BindingFlags.Instance); var concurrencyDetector = (IConcurrencyDetector)concurrencyDetectorField.GetValue(stateManager); // REFLECTION: Query.Provider._queryCompiler var queryCompilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompiler = queryCompilerField.GetValue(query.Provider); // REFLECTION: Query.Provider.NodeTypeProvider (Use property for nullable logic) var nodeTypeProviderField = queryCompiler.GetType().GetProperty("NodeTypeProvider", BindingFlags.NonPublic | BindingFlags.Instance); var nodeTypeProvider = nodeTypeProviderField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler.CreateQueryParser(); var createQueryParserMethod = queryCompiler.GetType().GetMethod("CreateQueryParser", BindingFlags.NonPublic | BindingFlags.Static); var createQueryParser = (QueryParser)createQueryParserMethod.Invoke(null, new[] { nodeTypeProvider }); // REFLECTION: Query.Provider._queryCompiler._database var databaseField = queryCompiler.GetType().GetField("_database", BindingFlags.NonPublic | BindingFlags.Instance); var database = (IDatabase)databaseField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler._evaluatableExpressionFilter var evaluatableExpressionFilterField = queryCompiler.GetType().GetField("_evaluatableExpressionFilter", BindingFlags.NonPublic | BindingFlags.Static); var evaluatableExpressionFilter = (IEvaluatableExpressionFilter)evaluatableExpressionFilterField.GetValue(null); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory var queryContextFactoryField = queryCompiler.GetType().GetField("_queryContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryContextFactory = (IQueryContextFactory)queryContextFactoryField.GetValue(queryCompiler); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory.CreateQueryBuffer var createQueryBufferDelegateMethod = (typeof(QueryContextFactory)).GetMethod("CreateQueryBuffer", BindingFlags.NonPublic | BindingFlags.Instance); var createQueryBufferDelegate = (Func <IQueryBuffer>)createQueryBufferDelegateMethod.CreateDelegate(typeof(Func <IQueryBuffer>), queryContextFactory); // REFLECTION: Query.Provider._queryCompiler._queryContextFactory._connection var connectionField = queryContextFactory.GetType().GetField("_connection", BindingFlags.NonPublic | BindingFlags.Instance); var connection = (IRelationalConnection)connectionField.GetValue(queryContextFactory); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory var queryCompilationContextFactoryField = typeof(Database).GetField("_queryCompilationContextFactory", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompilationContextFactory = (IQueryCompilationContextFactory)queryCompilationContextFactoryField.GetValue(database); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Logger var loggerField = queryCompilationContextFactory.GetType().GetProperty("Logger", BindingFlags.NonPublic | BindingFlags.Instance); var logger = (ISensitiveDataLogger)loggerField.GetValue(queryCompilationContextFactory); // CREATE connection var queryConnection = new CreateEntityRelationConnection(connection); // CREATE query context var queryContext = new RelationalQueryContext(createQueryBufferDelegate, connection, stateManager, concurrencyDetector); // CREATE new query from query visitor var newQuery = ParameterExtractingExpressionVisitor.ExtractParameters(query.Expression, queryContext, evaluatableExpressionFilter, logger); // PARSE new query var queryModel = createQueryParser.GetParsedQuery(newQuery); // CREATE query model visitor var queryModelVisitor = (RelationalQueryModelVisitor)queryCompilationContextFactory.Create(false).CreateQueryModelVisitor(); // REFLECTION: Query.Provider._queryCompiler._database._queryCompilationContextFactory.Create(false).CreateQueryModelVisitor().CreateQueryExecutor() var createQueryExecutorMethod = queryModelVisitor.GetType().GetMethod("CreateQueryExecutor"); var createQueryExecutorMethodGeneric = createQueryExecutorMethod.MakeGenericMethod(query.ElementType); var queryExecutor = (Func <QueryContext, IEnumerable <T> >)createQueryExecutorMethodGeneric.Invoke(queryModelVisitor, new[] { queryModel }); // CREATE a fake reader since EntityFramework close it queryConnection.OriginalDataReader = new CreateEntityDataReader(reader); var queryEnumerable = queryExecutor(queryContext); var enumerator = queryEnumerable.GetEnumerator(); while (enumerator.MoveNext()) { list.Add(enumerator.Current); } return(list); #endif }