### Production-Ready EF Core Second Level Cache Configuration Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/INDEX.md This example demonstrates a production-ready setup for EF Core Second Level Cache using Redis. It includes configuring the cache key prefix, disabling logging, and setting up a fallback to database calls if the cache provider is unavailable. ```csharp services.AddEFSecondLevelCache(options => options .UseStackExchangeRedisCacheProvider(redisConfig, TimeSpan.FromHours(1)) .UseCacheKeyPrefix("Prod_") .ConfigureLogging(false) .UseDbCallsIfCachingProviderIsDown(TimeSpan.FromMinutes(1)) ); ``` -------------------------------- ### Install NuGet Packages Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/README.md Install the main package and the memory cache provider using the .NET CLI. ```bash dotnet add package EFCoreSecondLevelCacheInterceptor dotnet add package EFCoreSecondLevelCacheInterceptor.MemoryCache ``` -------------------------------- ### Install Core Package Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Install the main package for the EFCore Second Level Cache Interceptor. ```bash # Core package dotnet add package EFCoreSecondLevelCacheInterceptor ``` -------------------------------- ### Install EasyCaching.Core Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/README.md Install the EasyCaching.Core provider for EF Core Second Level Cache Interceptor. ```bash dotnet add package EFCoreSecondLevelCacheInterceptor.EasyCaching.Core ``` -------------------------------- ### Add EFCoreSecondLevelCacheInterceptor Packages Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/integration-guide.md Install the main package and a cache provider package using the dotnet CLI. MemoryCache is shown as an example; other providers like StackExchange.Redis can be used. ```bash dotnet add package EFCoreSecondLevelCacheInterceptor dotnet add package EFCoreSecondLevelCacheInterceptor.MemoryCache # or another provider package ``` -------------------------------- ### Install CacheManager.Core Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/README.md Install the CacheManager.Core provider for EF Core Second Level Cache Interceptor. ```bash dotnet add package EFCoreSecondLevelCacheInterceptor.CacheManager.Core ``` -------------------------------- ### Install EasyCaching.Core Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Add the necessary NuGet packages for EasyCaching.Core integration. ```powershell dotnet add package EFCoreSecondLevelCacheInterceptor.EasyCaching.Core dotnet add package EasyCaching.Core ``` -------------------------------- ### Install Cache Provider Package Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Select and install one cache provider package based on your needs. ```bash # Select ONE provider package dotnet add package EFCoreSecondLevelCacheInterceptor.MemoryCache dotnet add package EFCoreSecondLevelCacheInterceptor.StackExchange.Redis dotnet add package EFCoreSecondLevelCacheInterceptor.FusionCache dotnet add package EFCoreSecondLevelCacheInterceptor.HybridCache dotnet add package EFCoreSecondLevelCacheInterceptor.EasyCaching.Core dotnet add package EFCoreSecondLevelCacheInterceptor.CacheManager.Core ``` -------------------------------- ### Install FusionCache Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/README.md Install the FusionCache provider for EF Core Second Level Cache Interceptor. ```bash dotnet add package EFCoreSecondLevelCacheInterceptor.FusionCache ``` -------------------------------- ### Basic Setup in Program.cs Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Register the cache interceptor service and configure the DbContext to use it. Ensure the interceptor is added to the DbContext options. ```csharp using EFCoreSecondLevelCacheInterceptor; // Register cache builder.Services.AddEFSecondLevelCache(options => options.UseMemoryCacheProvider() ); // Register DbContext with interceptor builder.Services.AddDbContextPool( (serviceProvider, optionsBuilder) => optionsBuilder .UseSqlServer(connectionString) .AddInterceptors( serviceProvider.GetRequiredService() ) ); ``` -------------------------------- ### Install StackExchange.Redis Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Installs the NuGet package for the StackExchange.Redis cache provider. Use this for distributed caching across multiple servers. ```powershell dotnet add package EFCoreSecondLevelCacheInterceptor.StackExchange.Redis ``` -------------------------------- ### EFCachePolicy Configuration Example Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-service-provider.md Demonstrates how to configure an EFCachePolicy with expiration mode, timeout, cache dependencies, and a salt key. ```csharp var policy = new EFCachePolicy() .ExpirationMode(CacheExpirationMode.Absolute) .Timeout(TimeSpan.FromHours(1)) .CacheDependencies("Users", "Orders") .SaltKey("report_123"); ``` -------------------------------- ### Query Caching Examples Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/INDEX.md Demonstrates how to apply query caching with default expiration, custom expiration, and how to skip caching for specific queries. ```csharp // Default (30 min) var data = context.Products.Cacheable().ToList(); ``` ```csharp // Custom expiration var data = context.Products .Cacheable(CacheExpirationMode.Sliding, TimeSpan.FromMinutes(15)) .ToList(); ``` ```csharp // Skip caching var data = context.Products.NotCacheable().ToList(); ``` -------------------------------- ### Configure EasyCaching Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Sets up EasyCaching, which supports multiple backends. This example uses in-memory. ```csharp services.AddEasyCaching(opts => opts.UseInMemory("default")); options.UseEasyCachingCoreProvider("default"); ``` -------------------------------- ### Install EasyCaching.Core Redis Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Add the NuGet packages for EasyCaching.Core with Redis and MessagePack serialization. ```powershell dotnet add package EasyCaching.Redis dotnet add package EasyCaching.Serialization.MessagePack ``` -------------------------------- ### Install In-Memory Cache Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Installs the NuGet package for the in-memory cache provider. Use this for development and single-server scenarios. ```powershell dotnet add package EFCoreSecondLevelCacheInterceptor.MemoryCache ``` -------------------------------- ### Install CacheManager Core Provider Packages Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Installs the necessary NuGet packages for using CacheManager.Core with EF Core Second Level Cache. ```powershell dotnet add package EFCoreSecondLevelCacheInterceptor.CacheManager.Core dotnet add package CacheManager.Core dotnet add package CacheManager.Microsoft.Extensions.Caching.Memory dotnet add package CacheManager.Serialization.Json ``` -------------------------------- ### Install HybridCache Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Add the NuGet package for HybridCache integration. ```powershell dotnet add package EFCoreSecondLevelCacheInterceptor.HybridCache ``` -------------------------------- ### Install FusionCache Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Add the necessary NuGet packages for FusionCache integration. ```powershell dotnet add package EFCoreSecondLevelCacheInterceptor.FusionCache dotnet add package ZiggyCreatures.FusionCache ``` -------------------------------- ### Custom SHA256 Hash Provider Example Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-service-provider.md Example implementation of IEFHashProvider using SHA256 for cache key hashing. Useful for different performance or security needs. ```csharp public class Sha256HashProvider : IEFHashProvider { public string ComputeHash(params string[] inputs) { var combined = string.Concat(inputs); using var sha = new System.Security.Cryptography.SHA256Managed(); var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(combined)); return Convert.ToHexString(hash); } } ``` -------------------------------- ### EFCacheKey Example Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-service-provider.md Shows how to create an EFCacheKey and use it to invalidate cache dependencies. This is useful for manually clearing cache entries related to specific tables. ```csharp var cacheKey = new EFCacheKey(new HashSet { "Users", "Orders" }) { KeyHash = "EB153BD4F...", DbContext = typeof(ApplicationDbContext) }; // Invalidate all queries depending on these tables cacheServiceProvider.InvalidateCacheDependencies(cacheKey); ``` -------------------------------- ### Install CacheManager Redis Package Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Installs the NuGet package for integrating CacheManager with Redis. ```powershell dotnet add package CacheManager.StackExchange.Redis ``` -------------------------------- ### Add EFCoreSecondLevelCacheInterceptor Package Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/README.md Install the main package for the EF Core Second Level Cache Interceptor. ```bash dotnet add package EFCoreSecondLevelCacheInterceptor ``` -------------------------------- ### Configure In-Memory Cache with CacheManager.Core Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/README.md Set up EFSecondLevelCache to use CacheManager.Core for in-memory caching. Ensure CacheManager.Core, CacheManager.Microsoft.Extensions.Caching.Memory, and CacheManager.Serialization.Json packages are installed. ```csharp services.AddEFSecondLevelCache(options => options.UseCacheManagerCoreProvider()); // Add CacheManager.Core services services.AddSingleton(typeof(ICacheManager<>), typeof(BaseCacheManager<>)); services.AddSingleton(typeof(ICacheManagerConfiguration), new CacheManager.Core.CacheConfigurationBuilder() .WithJsonSerializer() .WithMicrosoftMemoryCacheHandle("MemoryCache1") .Build()); ``` -------------------------------- ### Minimal EF Core Second Level Cache Setup Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/INDEX.md Use this minimal configuration to add EF Core Second Level Cache with an in-memory cache provider. Ensure services are configured before calling this method. ```csharp services.AddEFSecondLevelCache(options => options.UseMemoryCacheProvider() ); ``` -------------------------------- ### Register EF Core Second Level Cache Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/integration-guide.md Configure the EF Core Second Level Cache by selecting a cache provider, setting a cache key prefix, and optionally configuring logging and invalidation notifications. This setup should be done in your Program.cs or Startup.cs file. ```csharp using EFCoreSecondLevelCacheInterceptor; using Microsoft.Extensions.Caching.Memory; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); // 1. Register EF Core Second Level Cache builder.Services.AddEFSecondLevelCache(options => options // Select cache provider .UseMemoryCacheProvider() // Configure cache key prefix .UseCacheKeyPrefix("MyApp_") // Configure logging (development only) .ConfigureLogging( enable: builder.Environment.IsDevelopment(), cacheableEvent: args => { var logger = args.ServiceProvider .GetRequiredService() .CreateLogger("EFCaching"); switch (args.EventId) { case CacheableLogEventId.CacheHit: logger.LogDebug("Cache hit: {Key}", args.EFCacheKey?.KeyHash); break; case CacheableLogEventId.QueryResultCached: logger.LogDebug("Query cached: {Sql}", args.CommandText); break; case CacheableLogEventId.QueryResultInvalidated: logger.LogDebug("Cache invalidated for tables: {Tables}", string.Join(", ", args.EFCacheKey?.CacheDependencies ?? new HashSet())); break; } } ) // Notification callback .NotifyCacheInvalidation(invalidationInfo => { var logger = invalidationInfo.ServiceProvider .GetRequiredService() .CreateLogger("CacheInvalidation"); if (invalidationInfo.ClearAllCachedEntries) { logger.LogWarning("All cache entries were invalidated!"); } else { logger.LogInformation("Cache invalidated for: {Dependencies}", string.Join(", ", invalidationInfo.CacheDependencies)); } }) // Fallback to DB if cache provider is down .UseDbCallsIfCachingProviderIsDown(TimeSpan.FromMinutes(1)) // Skip caching for specific commands .SkipCachingCommands(commandText => commandText.Contains("NEWID()", StringComparison.OrdinalIgnoreCase)) // Skip caching empty results .SkipCachingResults(result => result.Value == null || (result.Value is EFTableRows rows && rows.RowsCount == 0)) ); // 2. Register DbContext var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContextPool( (serviceProvider, optionsBuilder) => optionsBuilder .UseSqlServer( connectionString, sqlOptions => { sqlOptions.CommandTimeout((int)TimeSpan.FromMinutes(3).TotalSeconds); sqlOptions.EnableRetryOnFailure(); } ) // Register the interceptor .AddInterceptors(serviceProvider.GetRequiredService()) ); // 3. Add other services builder.Services.AddControllersWithViews(); builder.Services.AddHttpContextAccessor(); // For tenant-aware caching ``` -------------------------------- ### EFCachedData Example Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-service-provider.md Illustrates creating an EFCachedData object for a SELECT query result and inserting it into the cache. This is typically done after executing a query that is intended to be cached. ```csharp var cachedResult = new EFCachedData { TableRows = new EFTableRows { Rows = new List { /* ... */ }, FieldCount = 3 } }; cacheServiceProvider.InsertValue(cacheKey, cachedResult, cachePolicy); ``` -------------------------------- ### Usage of Lock Provider in Interceptor Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/advanced-interfaces.md Example of using the ILockProvider within an interceptor to ensure thread-safe processing of reader results. ```csharp public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result) { using var @lock = _lockProvider.Lock(); // Process result while holding lock return _processor.ProcessReaderResult(command, eventData?.Context, result); } ``` -------------------------------- ### Configure StackExchange.Redis Cache Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/README.md Set up the EF Core Second Level Cache Interceptor to use StackExchange.Redis. This example configures connection options and a default cache duration. ```csharp var redisOptions = new ConfigurationOptions { EndPoints = { { "127.0.0.1", 6379 } }, AllowAdmin = true, ConnectTimeout = 10000 }; services.AddEFSecondLevelCache(options => options.UseStackExchangeRedisCacheProvider(redisOptions, TimeSpan.FromMinutes(5))); ``` -------------------------------- ### Configure Redis Cache with CacheManager.Core Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/README.md Integrate EFSecondLevelCache with CacheManager.Core for Redis caching. Install the CacheManager.StackExchange.Redis package. This configuration uses Redis with specific endpoint and keyspace event settings. ```csharp services.AddEFSecondLevelCache(options => options.UseCacheManagerCoreProvider()); // Add CacheManager.Core Redis services const string redisConfigurationKey = "redis"; services.AddSingleton(typeof(ICacheManagerConfiguration), new CacheManager.Core.CacheConfigurationBuilder() .WithJsonSerializer() .WithUpdateMode(CacheUpdateMode.Up) .WithRedisConfiguration(redisConfigurationKey, config => { config.WithAllowAdmin() .WithDatabase(0) .WithEndpoint("localhost", 6379) .EnableKeyspaceEvents(); }) .WithRedisCacheHandle(redisConfigurationKey) .Build()); services.AddSingleton(typeof(ICacheManager<>), typeof(BaseCacheManager<>)); ``` -------------------------------- ### Development Configuration Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/README.md Enable logging and the caching interceptor for development environments. ```csharp .ConfigureLogging(enable: true) .EnableCachingInterceptor(enable: true) ``` -------------------------------- ### Implement Mock Cache Service for Testing Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/integration-guide.md Create a mock implementation of IEFCacheServiceProvider for unit testing, ensuring cache misses by default. ```csharp public class MockCacheService : IEFCacheServiceProvider { public void ClearAllCachedEntries() { } public EFCachedData? GetValue(EFCacheKey cacheKey, EFCachePolicy cachePolicy) => null; // Always cache miss public void InsertValue(EFCacheKey cacheKey, EFCachedData? value, EFCachePolicy cachePolicy) { } public void InvalidateCacheDependencies(EFCacheKey cacheKey) { } } // In test setup services.AddSingleton(); ``` -------------------------------- ### EnableCachingInterceptor Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-options.md Enables or disables the caching interceptor entirely. This is useful for conditionally enabling caching, for example, only when not in a production environment. ```APIDOC ## EnableCachingInterceptor Enables or disables the caching interceptor entirely. ### Method `public EFCoreSecondLevelCacheOptions EnableCachingInterceptor(bool enable = true)` ### Parameters #### Path Parameters - **enable** (bool) - Optional - Whether to enable the interceptor (default: true) ### Returns **EFCoreSecondLevelCacheOptions** — This instance for fluent chaining. ### Example ```csharp services.AddEFSecondLevelCache(options => options.EnableCachingInterceptor(!environment.IsProduction()) ); ``` ``` -------------------------------- ### Configure EasyCaching.Core Dynamic Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Configure a dynamic EasyCaching.Core provider for multi-tenancy scenarios, determining the cache provider based on request headers. ```csharp services.AddEFSecondLevelCache(options => options.UseEasyCachingCoreProvider( (serviceProvider, cacheKey) => { var httpContext = serviceProvider .GetRequiredService() .HttpContext; var tenantId = httpContext?.Request.Headers["X-Tenant-Id"].ToString(); return $"redis-{tenantId ?? "default"}"; }, isHybridCache: false ) ); ``` -------------------------------- ### Get Cache Policy Method Signature Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/advanced-interfaces.md Signature for the GetCachePolicy method, which parses an EFCachePolicy from a given tag value and service provider. ```csharp EFCachePolicy? GetCachePolicy( string? tagValue, IServiceProvider serviceProvider) ``` -------------------------------- ### Implement Multi-Tenant Cache Key Prefixes Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/README.md Isolate caches per tenant by using dynamic cache key prefixes based on tenant ID. ```csharp .UseCacheKeyPrefix(serviceProvider => { var httpContext = serviceProvider .GetRequiredService() .HttpContext; var tenantId = httpContext?.Request.Headers["X-Tenant-Id"].ToString(); return $"EF_{tenantId}_"; }); ``` -------------------------------- ### Configure FusionCache Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Integrates FusionCache for L1/L2 hybrid caching. Requires adding FusionCache services. ```csharp services.AddFusionCache(); options.UseFusionCacheProvider(); ``` -------------------------------- ### Get Cache Key Method Signature Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/advanced-interfaces.md Signature for the GetEFCacheKey method, which computes a cache key based on the provided DbContext, IDbCommand, and EFCachePolicy. ```csharp EFCacheKey GetEFCacheKey( DbContext? dbContext, IDbCommand command, EFCachePolicy cachePolicy) ``` -------------------------------- ### Use Custom Cache Key Hash Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/integration-guide.md Replace the default xxHash64 provider with a custom implementation for hashing SQL commands and parameters, especially for larger parameter sets. ```csharp services.AddEFSecondLevelCache(options => options.UseCustomHashProvider() ); ``` -------------------------------- ### DbSet Overloads for Cacheable Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-query-extensions.md Provides overloads for the `Cacheable` extension method specifically for `DbSet` to simplify caching configuration when starting from a DbSet. ```APIDOC ## DbSet Cacheable Overloads All `Cacheable` methods also have overloads for `DbSet`: ### Method Signatures ```csharp public static IQueryable Cacheable(this DbSet query) where TType : class public static IQueryable Cacheable( this DbSet query, CacheExpirationMode expirationMode, TimeSpan? timeout = null) where TType : class public static IQueryable Cacheable( this DbSet query, CacheExpirationMode expirationMode, TimeSpan? timeout, string[] cacheDependencies) where TType : class public static IQueryable Cacheable( this DbSet query, CacheExpirationMode expirationMode, TimeSpan? timeout, string saltKey) where TType : class public static IQueryable Cacheable( this DbSet query, CacheExpirationMode expirationMode, TimeSpan? timeout, string[] cacheDependencies, string saltKey) where TType : class ``` ### Example ```csharp var users = context.Users .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromHours(2)) .ToList(); ``` ``` -------------------------------- ### Configure EasyCaching.Core In-Memory Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Configure the in-memory caching provider for EasyCaching and integrate with EF Core. ```csharp const string providerName = "InMemory1"; services.AddEasyCaching(options => { options.UseInMemory(config => { config.DBConfig = new InMemoryCachingOptions { SizeLimit = 10000 }; config.MaxRdSecond = 120; }, providerName); }); services.AddEFSecondLevelCache(options => options.UseEasyCachingCoreProvider(providerName, isHybridCache: false) .UseCacheKeyPrefix("EF_") ); ``` -------------------------------- ### Get Cache Key Prefix Method Signature Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/advanced-interfaces.md Signature for the GetCacheKeyPrefix method, which returns a string prefix for cache keys. It takes an IServiceProvider for dependency resolution. ```csharp string GetCacheKeyPrefix(IServiceProvider serviceProvider) ``` -------------------------------- ### Cacheable Log Event IDs Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/types.md Defines internal logging event IDs for various caching operations. These range from cache hits and misses to system start and errors. ```csharp public enum CacheableLogEventId { None = 0, CacheHit = 1001, QueryResultCached = 1002, QueryResultInvalidated = 1003, CachingSkipped = 1004, InvalidationSkipped = 1005, CachingSystemStarted = 1006, CachingError = 1007, QueryResultSuppressed = 1008, CacheDependenciesCalculated = 1009, CachePolicyCalculated = 1010 } ``` -------------------------------- ### appsettings.json Configuration Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/integration-guide.md Configure database connection strings and logging levels for EF Core and the second-level cache interceptor in `appsettings.json`. Ensure appropriate log levels are set for debugging. ```json { "ConnectionStrings": { "DefaultConnection": "Server=.;Database=MyDb;Integrated Security=true;" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.EntityFrameworkCore": "Debug", "EFCoreSecondLevelCacheInterceptor": "Debug" } } } ``` -------------------------------- ### Use Static Cache Key Prefix Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-options.md Sets a static prefix for all cache keys. This is a simple way to namespace your cache entries. ```csharp // Static prefix services.AddEFSecondLevelCache(options => options.UseCacheKeyPrefix("MyApp_") ); ``` -------------------------------- ### IEFCacheKeyProvider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/advanced-interfaces.md Computes cache keys from SQL commands and parameters. Implement this to customize how cache keys are generated. ```APIDOC ## IEFCacheKeyProvider ### Description Computes cache keys from SQL commands and parameters. ### Methods #### GetEFCacheKey ```csharp EFCacheKey GetEFCacheKey( DbContext? dbContext, IDbCommand command, EFCachePolicy cachePolicy) ``` Computes a cache key from the SQL command and its parameters. **Parameters** | Parameter | Type | Description | |-----------|------|-------------| | dbContext | DbContext? | Current DbContext | | command | IDbCommand | SQL command being executed | | cachePolicy | EFCachePolicy | Cache policy for this query | **Returns** — EFCacheKey with hash, DbContext, and dependencies. ``` -------------------------------- ### Configure Logging Events for Cache Interceptor Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/README.md Subscribe to caching events to log specific cache activities like hits, invalidations, or cached query results. This example shows how to log a QueryResultInvalidated event. ```csharp .ConfigureLogging(enable: environment.IsDevelopment(), cacheableEvent: args => { switch (args.EventId) { case CacheableLogEventId.CacheHit: break; case CacheableLogEventId.QueryResultCached: break; case CacheableLogEventId.QueryResultInvalidated: // Example of logging a specific event args.ServiceProvider.GetRequiredService() .CreateLogger(nameof(EFCoreSecondLevelCacheInterceptor)) .LogWarning("{EventId} -> {Message} -> {CommandText}", args.EventId, args.Message, args.CommandText); break; // ... handle other events } }) ``` -------------------------------- ### IEFCacheKeyPrefixProvider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/advanced-interfaces.md Provides dynamic or static prefixes for cache keys. Implement this to customize cache key prefixes, useful for multi-tenancy. ```APIDOC ## IEFCacheKeyPrefixProvider ### Description Provides dynamic or static prefixes for cache keys. ### Methods #### GetCacheKeyPrefix ```csharp string GetCacheKeyPrefix(IServiceProvider serviceProvider) ``` Returns a string prefix for cache keys. **Parameters** | Parameter | Type | Description | |-----------|------|-------------| | serviceProvider | IServiceProvider | DI container for resolving dependencies | **Returns** — String prefix for cache keys. ``` -------------------------------- ### Configure In-Memory Cache Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Use this for the simplest, single-process caching scenario. ```csharp options.UseMemoryCacheProvider() ``` -------------------------------- ### Use a Custom Hash Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-options.md Configures a custom hash provider for computing cache keys. The default is XxHash64Unsafe. Implement IEFHashProvider for custom algorithms. ```csharp public class CustomHashProvider : IEFHashProvider { public string ComputeHash(params string[] inputs) { // Custom hash implementation } } services.AddEFSecondLevelCache(options => options.UseCustomHashProvider() ); ``` -------------------------------- ### EFCacheKey Constructor Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-service-provider.md Initializes a new instance of the EFCacheKey class with specified cache dependencies. ```csharp public EFCacheKey(ISet cacheDependencies) ``` -------------------------------- ### Register Cache Services with In-Memory Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/README.md Register EF Core Second Level Cache services and configure the In-Memory cache provider in Startup.cs or Program.cs. ```csharp public void ConfigureServices(IServiceCollection services) { // 1. Add EF Core Second Level Cache services services.AddEFSecondLevelCache(options => options.UseMemoryCacheProvider().ConfigureLogging(true).UseCacheKeyPrefix("EF_") // Fallback on db if the caching provider fails. .UseDbCallsIfCachingProviderIsDown(TimeSpan.FromMinutes(1)) ); // 2. Add your DbContext var connectionString = Configuration["ConnectionStrings:ApplicationDbContextConnection"]; services.AddConfiguredMsSqlDbContext(connectionString); services.AddControllersWithViews(); } ``` -------------------------------- ### ILockProvider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/advanced-interfaces.md Provides synchronization for thread-safe cache operations. Implement this to customize how cache access is synchronized. ```APIDOC ## ILockProvider ### Description Provides synchronization for thread-safe cache operations. ### Methods #### Lock ```csharp IDisposable Lock() ``` Returns a disposable lock for synchronous operations. #### LockAsync ```csharp ValueTask LockAsync(CancellationToken cancellationToken = default) ``` Returns an async-disposable lock for async operations. ``` -------------------------------- ### Configure EasyCaching.Core Redis Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Configure the Redis caching provider for EasyCaching with MessagePack serialization and integrate with EF Core. ```csharp const string providerName = "Redis1"; services.AddEasyCaching(options => { options.UseRedis(config => { config.DBConfig.Endpoints.Add( new ServerEndPoint("127.0.0.1", 6379) ); config.SerializerName = "Pack"; }, providerName) .WithMessagePack("Pack"); }); services.AddEFSecondLevelCache(options => options.UseEasyCachingCoreProvider(providerName, isHybridCache: false) .UseCacheKeyPrefix("EF_") ); ``` -------------------------------- ### Basic Caching with Defaults Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/integration-guide.md Use `.Cacheable()` for basic caching with a default absolute expiration of 30 minutes. This is suitable for frequently accessed, rarely changing data. ```csharp public async Task> GetAllProductsAsync() { return await _context.Products .Cacheable() .ToListAsync(); } ``` -------------------------------- ### UseCacheKeyPrefix Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-options.md Sets a static or dynamic prefix for all cache keys. This is useful for organizing cache entries or for multi-tenant scenarios. ```APIDOC ## UseCacheKeyPrefix ### Description Sets a static or dynamic prefix for all cache keys. This is useful for organizing cache entries or for multi-tenant scenarios. ### Overload 1: Static Prefix ```csharp public EFCoreSecondLevelCacheOptions UseCacheKeyPrefix(string prefix) ``` ### Overload 2: Dynamic Prefix ```csharp public EFCoreSecondLevelCacheOptions UseCacheKeyPrefix(Func? prefix) ``` ### Parameters * **prefix** (string) - Required (Overload 1) - Static prefix for all cache keys * **prefix** (Func<IServiceProvider, string>?) - Optional (Overload 2) - Function to compute prefix dynamically ### Returns **EFCoreSecondLevelCacheOptions** - This instance for fluent chaining. ### Remarks The default prefix is "EF_". Dynamic prefixes are useful for multi-tenant scenarios where different tenants should have separate caches. ### Example ```csharp // Static prefix services.AddEFSecondLevelCache(options => options.UseCacheKeyPrefix("MyApp_") ); // Dynamic prefix based on tenant services.AddEFSecondLevelCache(options => options.UseCacheKeyPrefix(serviceProvider => { var httpContext = serviceProvider .GetRequiredService() .HttpContext; var tenantId = httpContext?.Request.Headers["X-Tenant-Id"].ToString() ?? "default"; return $"EF_{tenantId}_"; }) ); ``` ``` -------------------------------- ### UseCustomCacheProvider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-options.md Configures a custom cache service provider. Overload 1 allows specifying the type of the custom cache provider. ```APIDOC ## UseCustomCacheProvider ### Description Configures a custom cache service provider. ### Overload 1: Type-Only ### Method ```csharp public EFCoreSecondLevelCacheOptions UseCustomCacheProvider() where T : IEFCacheServiceProvider ``` ### Type Parameters - **T** - A class implementing IEFCacheServiceProvider ``` -------------------------------- ### Configure Dynamic Cache Key Prefix Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Set a dynamic prefix for cache keys based on runtime context, such as tenant ID from HTTP headers. This is crucial for multi-tenant applications. ```csharp // Dynamic prefix (multi-tenant) options.UseCacheKeyPrefix(serviceProvider => { var httpContext = serviceProvider .GetRequiredService() .HttpContext; var tenantId = httpContext?.Request.Headers["X-Tenant-Id"].ToString(); return $"EF_Tenant{tenantId}_"; }); ``` -------------------------------- ### Configure FusionCache for EF Core Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Configure FusionCache options and register the EF Core caching provider. ```csharp // 1. Configure FusionCache services.AddFusionCache() .WithOptions(options => { options.DefaultEntryOptions = new FusionCacheEntryOptions { Duration = TimeSpan.FromMinutes(10), IsFailSafeEnabled = true, FailSafeMaxDuration = TimeSpan.FromHours(1) }; }); // 2. Add EF Core caching with FusionCache provider services.AddEFSecondLevelCache(options => options.UseFusionCacheProvider() ); ``` -------------------------------- ### Register Services and DbContext Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/README.md Register the caching services and add the interceptor to your DbContext configuration in Program.cs. ```csharp using EFCoreSecondLevelCacheInterceptor; builder.Services.AddEFSecondLevelCache(options => options .UseMemoryCacheProvider() .UseCacheKeyPrefix("EF_") .ConfigureLogging(true) ); builder.Services.AddDbContextPool( (serviceProvider, optionsBuilder) => optionsBuilder .UseSqlServer(connectionString) .AddInterceptors( serviceProvider.GetRequiredService() ) ); ``` -------------------------------- ### ConfigureLogging Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-options.md Enables debug logging for caching events. This can help in diagnosing caching issues but should be used cautiously in production due to performance implications. ```APIDOC ## ConfigureLogging ### Description Enables debug logging for caching events. This can help in diagnosing caching issues but should be used cautiously in production due to performance implications. ### Method Signature ```csharp public EFCoreSecondLevelCacheOptions ConfigureLogging( bool enable = false, Action? cacheableEvent = null) ``` ### Parameters * **enable** (bool) - Optional - Whether to enable logging (default: false) * **cacheableEvent** (Action<EFCacheableLogEvent>?) - Optional - Callback for logging events (default: null) ### Returns **EFCoreSecondLevelCacheOptions** - This instance for fluent chaining. ### Remarks Logging has performance implications. Disable for production or only enable for development. Events include cache hits, misses, invalidations, and errors. ### Example ```csharp services.AddEFSecondLevelCache(options => options.ConfigureLogging( enable: environment.IsDevelopment(), cacheableEvent: args => { if (args.EventId == CacheableLogEventId.CacheHit) { logger.LogInformation("Cache hit for: {CommandText}", args.CommandText); } } ) ); ``` ``` -------------------------------- ### Table Name Comparison Options Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Options for comparing table names when defining caching rules. ```csharp TableNameComparison.Contains TableNameComparison.DoesNotContain TableNameComparison.StartsWith TableNameComparison.DoesNotStartWith TableNameComparison.EndsWith TableNameComparison.DoesNotEndWith TableNameComparison.ContainsOnly TableNameComparison.ContainsEvery TableNameComparison.DoesNotContainEvery ``` -------------------------------- ### Use a Custom Cache Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-options.md Configures a custom cache service provider. This overload allows specifying the custom cache provider type. ```csharp public EFCoreSecondLevelCacheOptions UseCustomCacheProvider() where T : IEFCacheServiceProvider ``` -------------------------------- ### Use Dynamic Cache Key Prefix Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-options.md Configures a dynamic prefix for cache keys based on the provided service provider. This is particularly useful in multi-tenant applications to ensure cache isolation between tenants. ```csharp // Dynamic prefix based on tenant services.AddEFSecondLevelCache(options => options.UseCacheKeyPrefix(serviceProvider => { var httpContext = serviceProvider .GetRequiredService() .HttpContext; var tenantId = httpContext?.Request.Headers["X-Tenant-Id"].ToString() ?? "default"; return $"EF_{tenantId}_"; }) ); ``` -------------------------------- ### Custom Cache Provider Implementation Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Implements the IEFCacheServiceProvider interface using a dictionary to store cached data. Supports absolute and sliding expiration modes. Handles cache invalidation based on dependencies and provides a method to clear all entries. ```csharp public class CustomCacheProvider : IEFCacheServiceProvider { private readonly Dictionary _cache = new(); public EFCachedData? GetValue(EFCacheKey cacheKey, EFCachePolicy cachePolicy) { if (!_cache.TryGetValue(cacheKey.KeyHash, out var entry)) return null; if (entry.Expiry < DateTime.UtcNow) { _cache.Remove(cacheKey.KeyHash); return null; } // Update sliding expiration if (cachePolicy.CacheExpirationMode == CacheExpirationMode.Sliding) { var newExpiry = DateTime.UtcNow.Add(cachePolicy.CacheTimeout ?? TimeSpan.FromMinutes(20)); _cache[cacheKey.KeyHash] = (entry.Data, newExpiry); } return entry.Data; } public void InsertValue(EFCacheKey cacheKey, EFCachedData? value, EFCachePolicy cachePolicy) { var expiry = cachePolicy.CacheExpirationMode == CacheExpirationMode.NeverRemove ? DateTime.MaxValue : DateTime.UtcNow.Add(cachePolicy.CacheTimeout ?? TimeSpan.FromMinutes(20)); _cache[cacheKey.KeyHash] = (value ?? new EFCachedData(), expiry); } public void InvalidateCacheDependencies(EFCacheKey cacheKey) { // Find and remove all entries depending on these tables var keysToRemove = _cache .Where(kvp => cacheKey.CacheDependencies.Any( dep => kvp.Key.Contains(dep, StringComparison.OrdinalIgnoreCase))) .Select(kvp => kvp.Key) .ToList(); foreach (var key in keysToRemove) _cache.Remove(key); } public void ClearAllCachedEntries() { _cache.Clear(); } } ``` -------------------------------- ### Table Name Comparison Strategies Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/types.md Specifies how table names are matched when applying caching policies. Choose from various comparison methods like Contains, StartsWith, EndsWith, or exact matches. ```csharp public enum TableNameComparison { Contains, DoesNotContain, EndsWith, DoesNotEndWith, StartsWith, DoesNotStartWith, ContainsOnly, ContainsEvery, DoesNotContainEvery } ``` ```csharp // Cache queries on Products and Categories tables options.CacheQueriesContainingTableNames( CacheExpirationMode.Absolute, TimeSpan.FromMinutes(30), TableNameComparison.Contains, "Products", "Categories" ); // Cache only queries that contain exactly these tables options.CacheQueriesContainingTableNames( CacheExpirationMode.Absolute, TimeSpan.FromMinutes(30), TableNameComparison.ContainsOnly, "Products" ); ``` -------------------------------- ### Configure Caching Event Logging Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/README.md Subscribe to caching lifecycle events and log them using a provided logger. ```csharp .ConfigureLogging(enable: true, cacheableEvent: args => { logger.LogInformation("{EventId}: {Message}", args.EventId, args.Message); }); ``` -------------------------------- ### Define Cache Key Prefix Provider Interface Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/advanced-interfaces.md Interface for providing dynamic or static prefixes for cache keys. This is useful for scenarios like multi-tenancy. ```csharp public interface IEFCacheKeyPrefixProvider { string GetCacheKeyPrefix(IServiceProvider serviceProvider); } ``` -------------------------------- ### Configure Distributed Cache with Redis Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/integration-guide.md Integrate with Redis for distributed caching in load-balanced environments. Configure connection endpoints and expiration policies. ```csharp services.AddEFSecondLevelCache(options => { var redisOptions = new ConfigurationOptions { EndPoints = { { "redis.example.com", 6379 } }, AllowAdmin = true, ConnectTimeout = 10000 }; options.UseStackExchangeRedisCacheProvider( redisOptions, TimeSpan.FromHours(1) ); }); ``` -------------------------------- ### Configure HybridCache for EF Core Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Register the HybridCache provider and set a cache key prefix. ```csharp services.AddHybridCache(); services.AddEFSecondLevelCache(options => options.UseHybridCacheProvider() .UseCacheKeyPrefix("EF_") ); ``` -------------------------------- ### Configure Caching for All Queries Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-options.md Enables caching for all queries globally. Individual queries can override this behavior. Use this for a general caching strategy. ```csharp services.AddEFSecondLevelCache(options => options.CacheAllQueries(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(30)) ); ``` -------------------------------- ### UseCustomHashProvider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-options.md Configures a custom hash provider for computing cache keys. Allows specifying a custom implementation of IEFHashProvider. ```APIDOC ## UseCustomHashProvider ### Description Configures a custom hash provider for computing cache keys. ### Method ```csharp public EFCoreSecondLevelCacheOptions UseCustomHashProvider() where T : IEFHashProvider ``` ### Type Parameters - **T** - A class implementing IEFHashProvider ### Returns **EFCoreSecondLevelCacheOptions** - This instance for fluent chaining. ### Remarks The default hash provider is `XxHash64Unsafe`, a fast non-cryptographic algorithm. Implement `IEFHashProvider` to use a different algorithm. ### Example ```csharp public class CustomHashProvider : IEFHashProvider { public string ComputeHash(params string[] inputs) { // Custom hash implementation } } services.AddEFSecondLevelCache(options => options.UseCustomHashProvider() ); ``` ``` -------------------------------- ### Define Custom Hash Provider Interface Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/advanced-interfaces.md Interface for customizing cache key hash computation. Implement this to provide your own hashing logic. ```csharp public interface IEFHashProvider { string ComputeHash(params string[] inputs); } ``` -------------------------------- ### Configure Multi-Tenant Cache Isolation Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/integration-guide.md Set a cache key prefix based on the tenant ID from the request headers to ensure cache isolation between tenants. ```csharp services.AddEFSecondLevelCache(options => options .UseCacheKeyPrefix(serviceProvider => { var httpContext = serviceProvider .GetRequiredService() .HttpContext; var tenantId = httpContext?.Request.Headers["X-Tenant-Id"].ToString() ?? "default"; return $"EF_Tenant{tenantId}_"; }) ); ``` -------------------------------- ### Global Caching Configuration Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/integration-guide.md Configure global caching policies using `AddEFSecondLevelCache`. This includes caching all queries by default or excluding specific tables from global caching. ```csharp services.AddEFSecondLevelCache(options => options // Cache all queries by default .CacheAllQueries(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(30)) // Exclude specific tables .CacheAllQueriesExceptContainingTableNames( CacheExpirationMode.Absolute, TimeSpan.FromMinutes(30), "AuditLog", "TemporaryData" ) ); ``` -------------------------------- ### Configure Logging for Cache Events Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/types.md Configure logging to capture cache-related events. Use this to log cache hits, invalidations, and errors. ```csharp options.ConfigureLogging(enable: true, cacheableEvent: args => { switch (args.EventId) { case CacheableLogEventId.CacheHit: logger.LogInformation("Cache hit for: {Key}", args.EFCacheKey?.KeyHash); break; case CacheableLogEventId.QueryResultInvalidated: logger.LogWarning("Cache invalidated for: {Dependencies}", string.Join(", ", args.EFCacheKey?.CacheDependencies ?? new HashSet())); break; case CacheableLogEventId.CachingError: logger.LogError("Caching error: {Message}", args.Message); break; } }); ``` -------------------------------- ### Configure Static Cache Key Prefix Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Set a static prefix for all cache keys generated by the interceptor. This helps in organizing cache entries and avoiding key collisions. ```csharp // Static prefix options.UseCacheKeyPrefix("MyApp_"); ``` -------------------------------- ### Cacheable Query with Dependencies and Salt Key Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-query-extensions.md Configures a query to be cacheable with specific expiration, dependencies, and a custom salt key. Use this when you need fine-grained control over cache invalidation and key generation. ```csharp public static IQueryable Cacheable( this IQueryable query, CacheExpirationMode expirationMode, TimeSpan? timeout, string[] cacheDependencies, string saltKey) { // Implementation details omitted for brevity return query; } ``` ```csharp var customQuery = context.Orders .Where(x => x.CustomerId == customerId) .Cacheable( CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45), new[] { "Orders", "OrderDetails", "Customers" }, $"customer_{customerId}" ) .ToListAsync(); ``` -------------------------------- ### Configure Memory Cache with Short Absolute Timeout Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/integration-guide.md Reduce memory usage by configuring the in-memory cache provider with a short absolute expiration time. ```csharp services.AddEFSecondLevelCache(options => options.UseMemoryCacheProvider( CacheExpirationMode.Absolute, TimeSpan.FromMinutes(5) // Short timeout ) ); ``` -------------------------------- ### Configure Logging for Cache Events Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/types.md Configure custom logging for cacheable events. This allows you to log detailed information about cache hits, misses, and SQL commands. ```csharp options.ConfigureLogging(enable: true, cacheableEvent: logEvent => { var logger = logEvent.ServiceProvider .GetRequiredService() .CreateLogger("EFCaching"); logger.LogInformation( "{EventId}: {Message}\nSQL: {Sql}", logEvent.EventId, logEvent.Message, logEvent.CommandText ); }); ``` -------------------------------- ### Configure HybridCache Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/README.md Enable the EF Core Second Level Cache Interceptor to use the .NET HybridCache provider. This is a straightforward registration process. ```csharp services.AddEFSecondLevelCache(options => options.UseHybridCacheProvider()); ``` -------------------------------- ### Configure In-Memory Cache Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/cache-providers.md Registers the in-memory cache provider with a custom cache key prefix and logging enabled. ```csharp services.AddEFSecondLevelCache(options => options.UseMemoryCacheProvider() .UseCacheKeyPrefix("EF_") .ConfigureLogging(true) ); ``` -------------------------------- ### Cacheable() with Expiration, Timeout, and Salt Key Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-query-extensions.md Enables caching with custom expiration, timeout, and an additional salt key. Use a salt key to differentiate cache entries for queries that are structurally similar but have different contextual meanings. ```csharp public static IQueryable Cacheable( this IQueryable query, CacheExpirationMode expirationMode, TimeSpan? timeout, string saltKey) ``` ```csharp var tenantPosts = context.Posts .Where(x => x.TenantId == tenantId) .Cacheable( CacheExpirationMode.Sliding, TimeSpan.FromMinutes(30), $"tenant_{tenantId}" ) .ToList(); ``` -------------------------------- ### Configure HybridCache Provider Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Uses the .NET 8+ built-in HybridCache for caching. ```csharp services.AddHybridCache(); options.UseHybridCacheProvider(); ``` -------------------------------- ### EFCachePolicy Static Factory Method Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-service-provider.md Configures EFCachePolicy using an action and returns a serialized string representation, used internally as a query tag. ```csharp public static string Configure(Action options) ``` -------------------------------- ### Cache Query with Dependencies Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Cache query results with specified dependencies. The cache entry will be invalidated if any of the listed tables are modified. ```csharp var data = context.Products .Cacheable( CacheExpirationMode.Absolute, TimeSpan.FromHours(1), new[] { "Products", "Categories" } ) .ToList(); ``` -------------------------------- ### Production In-Memory Cache Configuration Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/README.md Configure the in-memory cache provider with a specific expiration and disable logging for production. ```csharp .UseMemoryCacheProvider(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(20)) .ConfigureLogging(enable: false) .UseCacheKeyPrefix("Prod_") ``` -------------------------------- ### Production Redis Cache Configuration Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/README.md Configure the StackExchange.Redis cache provider with specified options and a fallback to database calls. ```csharp var redisOptions = new ConfigurationOptions { EndPoints = { { "redis.example.com", 6379 } }, AllowAdmin = true }; .UseStackExchangeRedisCacheProvider(redisOptions, TimeSpan.FromHours(1)) .UseDbCallsIfCachingProviderIsDown(TimeSpan.FromMinutes(1)) ``` -------------------------------- ### Table Type Comparison Strategies Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/types.md Specifies how entity types are matched when applying caching policies. Supports matching based on containment, exact matches, or all specified types. ```csharp public enum TableTypeComparison { Contains, DoesNotContain, ContainsOnly, ContainsEvery, DoesNotContainEvery } ``` ```csharp options.CacheQueriesContainingTypes( CacheExpirationMode.Absolute, TimeSpan.FromMinutes(30), TableTypeComparison.Contains, typeof(Product), typeof(Category) ); ``` -------------------------------- ### Implement Per-User Caching Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/quick-reference.md Caches user-specific data using a sliding expiration and a cache key incorporating the user ID. ```csharp var userPosts = context.Posts .Where(p => p.UserId == userId) .Cacheable( CacheExpirationMode.Sliding, TimeSpan.FromMinutes(30), $"user_{userId}" ) .ToList(); ``` -------------------------------- ### Enable Fallback to Database When Cache Provider is Down Source: https://github.com/vahidn/efcoresecondlevelcacheinterceptor/blob/master/_autodocs/api-reference-cache-options.md Configure the interceptor to fall back to direct database calls if the configured caching provider becomes unavailable. Specify how often to check for the provider's availability. ```csharp services.AddEFSecondLevelCache(options => options .UseStackExchangeRedisCacheProvider(redisOptions) .UseDbCallsIfCachingProviderIsDown(TimeSpan.FromMinutes(1)) ); ```