/// <summary> /// Returns a new query where the result will be cached base on the <see cref="TimeSpan"/> parameter. /// </summary> /// <typeparam name="T">The type of entity being queried.</typeparam> /// <param name="source">The source query.</param> /// <param name="options">Options how to handle cached query results.</param> /// <returns>A new query where the result set will be cached.</returns> public static IQueryable <T> Cacheable <T>(this IQueryable <T> source, [NotParameterized] CacheableOptions options) { Check.NotNull(source, nameof(source)); Check.NotNull(options, nameof(options)); return (source.Provider is EntityQueryProvider ? source.Provider.CreateQuery <T>( Expression.Call( instance: null, method: CacheableMethodInfo.MakeGenericMethod(typeof(T)), arg0: source.Expression, arg1: Expression.Constant(options))) : source); }
private static Boolean ShouldResultBeCached <TResult>(TResult result, CacheableOptions options) { if (!options.CacheNullResult && result == null) { return(false); } if (result is IEnumerable) { var enumerable = result as IEnumerable; return(enumerable.Any()); } return(true); }
private static async Task <TResult> ExecuteSingletonAsyncQuery <TResult>( QueryContext queryContext, Func <QueryContext, IAsyncEnumerable <TResult> > compiledQuery, IDiagnosticsLogger <DbLoggerCategory.Query> logger, Type contextType, Func <object, Exception, string> logFormatter, ICacheProvider cacheProvider, object queryKey, CacheableOptions options) { try { var asyncEnumerable = compiledQuery(queryContext); using (var asyncEnumerator = asyncEnumerable.GetEnumerator()) { await asyncEnumerator.MoveNext(queryContext.CancellationToken); if (cacheProvider != null) { // add query result to cache if (ShouldResultBeCached(asyncEnumerator.Current, options)) { cacheProvider.SetCachedResult <TResult>(queryKey, asyncEnumerator.Current, options.TimeToLive); } logger.Logger.Log <object>(LogLevel.Debug, CacheableEventId.QueryResultCached, queryKey, null, logFormatter); } return(asyncEnumerator.Current); } } catch (Exception exception) { logger.QueryIterationFailed(contextType, exception); throw; } }