/// <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);
        }
示例#2
0
        /// <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;
 }
示例#4
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;
 }
示例#8
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 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;
 }
示例#11
0
 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;
 }
示例#12
0
 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;
 }
示例#15
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(
     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;
 }
示例#16
0
        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);
        }
示例#17
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 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);
        }
示例#19
0
        // 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()}");
            }
        }
示例#23
0
        /// <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);
        }
示例#24
0
        //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;
        }
示例#25
0
        /// <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);
        }
示例#26
0
        /// <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());
        }
示例#27
0
        /// <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);
        }
示例#30
0
        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
        }