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