CachedQueries is an open-source .NET library for adding efficient caching to Entity Framework queries. It simplifies caching IQueryable results by enabling caching directly within EF, thus eliminating the need for extra abstraction layers over DbSet.
- Install package
dotnet add package CachedQueries
- Dependency Injection Setup (example using memory cache):
// Setup system cache
services.AddMemoryCache();
// Add CachedQueries to your services
services.AddQueriesCaching(options =>
options
.UseCacheStore(MemoryCache)
.UseEntityFramework());
// Use CachedQueries in your application
app.UseQueriesCaching();
- Cache Invalidation Integration
// Extend SaveChanges and SaveChangesAsync methods in EF context
public override async Task<int> SaveChangesAsync(CancellationToken token = default)
{
// Invoke cache expiration
await ChangeTracker.ExpireEntitiesCacheAsync(token);
return await base.SaveChangesAsync(token);
}
Easily cache collections, including related data:
// Standard caching
var results = await context.Blogs
.Include(x => x.Posts)
.ToCachedListAsync(cancellationToken);
// Caching with expiration
var results = await context.Posts
.ToCachedListAsync(TimeSpan.FromHours(8), cancellationToken);
// Caching with custom tags
var results = await context.Posts
.ToCachedListAsync(TimeSpan.FromHours(8), new List<string> { "custom_tag" }, cancellationToken);
Cache single entities:
// Cache a single entity based on a condition
var result = await context.Blogs
.Include(x => x.Posts)
.CachedFirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken);
// Cache an entity with a predetermined expiration time
var result = await context.Posts
.CachedFirstOrDefaultAsync(TimeSpan.FromHours(8), cancellationToken);
// Cache using custom tags for nuanced control
var result = await context.Posts
.CachedFirstOrDefaultAsync(TimeSpan.FromHours(8), new List<string> { "custom_tag" }, cancellationToken);
CachedQueries efficiently handles cache invalidation, maintaining data accuracy and relevance.
To integrate automatic cache invalidation within CachedQueries, it is efficient to override the EF context SaveChanges
and SaveChangesAsync
methods.
public override async Task<int> SaveChangesAsync(CancellationToken token = default)
{
await ChangeTracker.ExpireEntitiesCacheAsync(token);
return base.SaveChangesAsync(token);
}
Control cache updates in case using custom tags:
// Setup the cache invalidator (typically done during initialization)
private ICacheInvalidator _cacheInvalidator;
...
// Invalidate specific cache segments by custom tag
_cacheInvalidator.InvalidateCacheAsync(new List<string> { "custom_tag" })
Use Redis for scalable, distributed caching:
// Setup distributed cache
services.AddDistributedCache();
// Setup Redis
services.AddStackExchangeRedisCache(config);
// Add CachedQueries to your services
services.AddQueriesCaching(options =>
options
.UseCacheStore(DistributedCache)
.UseLockManager<RedisLockManager>()
.UseEntityFramework());
// Use CachedQueries in your application
app.UseQueriesCaching();
Customize key aspects for specific needs:
- Cache Key Factory: Allows for the implementation of unique logic in generating cache keys.
- Lock Manager: Customization of concurrent access and locking strategies for cache entries.
- Cache Options: Enables the setting and adjustment of global cache settings.
- Cache Invalidator: Provides the capability to devise specific rules for invalidating cache entries.
Custom Dependency Injection example:
services.AddQueriesCaching(options =>
options
.UseOptions(new CacheOptions {
LockTimeout = TimeSpan.FromSeconds(10),
DefaultExpiration = TimeSpan.FromMinutes(30)
})
.UseCacheStore(CustomCacheStore) // ICacheStore implementation
.UseCacheStoreProvider(CustomCacheStoreProvider) // ICacheStoreProvider implementation
.UseCacheInvalidator(CustomCacheInvalidator) // ICacheInvalidator implementation
.UseLockManager(CustomLockManager) // ILockManager implementation
.UseKeyFactory(CustomKeyFactory) // ICacheKeyFactory implementation
.UseEntityFramework()); // Integration with Entity Framework
// Activation of CachedQueries in applications
app.UseQueriesCaching();
Discover more about CachedQueries through the library's test cases, offering insights into detailed functionalities and advanced usage examples.