private bool Equals(CommandCacheKey commandCacheKey)
            {
                if (!ReferenceEquals(_selectExpression, commandCacheKey._selectExpression))
                {
                    return(false);
                }

                if (_parameterValues.Count > 0)
                {
                    foreach (var parameterValue in _parameterValues)
                    {
                        var value = parameterValue.Value;
                        if (!commandCacheKey._parameterValues.TryGetValue(parameterValue.Key, out var otherValue))
                        {
                            return(false);
                        }

                        // ReSharper disable once ArrangeRedundantParentheses
                        if ((value == null) != (otherValue == null))
                        {
                            return(false);
                        }

                        if (value is IEnumerable &&
                            value.GetType() == typeof(object[]))
                        {
                            // FromSql parameters must have the same number of elements
                            return(((object[])value).Length == (otherValue as object[])?.Length);
                        }
                    }
                }

                return(true);
            }
        public virtual IRelationalCommand GetRelationalCommand(IReadOnlyDictionary <string, object> parameters)
        {
            var cacheKey = new CommandCacheKey(_selectExpression, parameters);

retry:
            if (!_memoryCache.TryGetValue(cacheKey, out IRelationalCommand relationalCommand))
            {
                if (!_syncObjects.TryAdd(cacheKey, value: null))
                {
                    goto retry;
                }

                try
                {
                    var(selectExpression, canCache) =
                        _relationalParameterBasedQueryTranslationPostprocessor.Optimize(_selectExpression, parameters);
                    relationalCommand = _querySqlGeneratorFactory.Create().GetCommand(selectExpression);

                    if (canCache)
                    {
                        _memoryCache.Set(cacheKey, relationalCommand, new MemoryCacheEntryOptions {
                            Size = 10
                        });
                    }
                }
                finally
                {
                    _syncObjects.TryRemove(cacheKey, out _);
                }
            }

            return(relationalCommand);
        }
Esempio n. 3
0
            public virtual IRelationalCommand GetRelationalCommand(IReadOnlyDictionary <string, object> parameters)
            {
                var key = new CommandCacheKey(parameters);

                if (_commandCache.TryGetValue(key, out var relationalCommand))
                {
                    return(relationalCommand);
                }

                var selectExpression = _parameterValueBasedSelectExpressionOptimizer.Optimize(_selectExpression, parameters);

                relationalCommand = _querySqlGeneratorFactory.Create().GetCommand(selectExpression);

                if (ReferenceEquals(selectExpression, _selectExpression))
                {
                    _commandCache.TryAdd(key, relationalCommand);
                }

                return(relationalCommand);
            }
        /// <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 virtual IRelationalCommand GetRelationalCommand([NotNull] IReadOnlyDictionary <string, object> parameters)
        {
            var cacheKey = new CommandCacheKey(_selectExpression, parameters);

            if (_memoryCache.TryGetValue(cacheKey, out IRelationalCommand relationalCommand))
            {
                return(relationalCommand);
            }

            // When multiple threads attempt to start processing the same query (program startup / thundering
            // herd), have only one actually process and block the others.
            // Note that the following synchronization isn't perfect - some race conditions may cause concurrent
            // processing. This is benign (and rare).
            var compilationLock = _locks.GetOrAdd(cacheKey, _ => new object());

            try
            {
                lock (compilationLock)
                {
                    if (!_memoryCache.TryGetValue(cacheKey, out relationalCommand))
                    {
                        var selectExpression = _relationalParameterBasedSqlProcessor.Optimize(
                            _selectExpression, parameters, out var canCache);
                        relationalCommand = _querySqlGeneratorFactory.Create().GetCommand(selectExpression);

                        if (canCache)
                        {
                            _memoryCache.Set(cacheKey, relationalCommand, new MemoryCacheEntryOptions {
                                Size = 10
                            });
                        }
                    }

                    return(relationalCommand);
                }
            }
            finally
            {
                _locks.TryRemove(compilationLock, out _);
            }
        }
Esempio n. 5
0
        public virtual IRelationalCommand GetRelationalCommand(
            [NotNull] IReadOnlyDictionary <string, object> parameters)
        {
            IRelationalCommand relationalCommand;
            var key = new CommandCacheKey(parameters);

            if (_commandCache.TryGetValue(key, out relationalCommand))
            {
                return(relationalCommand);
            }

            var generator = QuerySqlGeneratorFactory();

            relationalCommand = generator.GenerateSql(parameters);

            if (generator.IsCacheable)
            {
                _commandCache.TryAdd(key, relationalCommand);
            }

            return(relationalCommand);
        }
        /// <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 IRelationalCommand GetRelationalCommand(
            [NotNull] IReadOnlyDictionary<string, object> parameters)
        {
            IRelationalCommand relationalCommand;
            var key = new CommandCacheKey(parameters);

            if (_commandCache.TryGetValue(key, out relationalCommand))
            {
                return relationalCommand;
            }

            var generator = QuerySqlGeneratorFactory();
            relationalCommand = generator.GenerateSql(parameters);

            if (generator.IsCacheable)
            {
                _commandCache.TryAdd(key, relationalCommand);
            }

            return relationalCommand;
        }