$ show VahidN/EFCoreSecondLevelCacheInterceptor
This repository is a .NET library (distributed as NuGet packages) that adds a second-level query cache to Entity Framework Core applications. In production, it registers a DbCommandInterceptor that intercepts every EF Core database command: SELECT queries are converted into a cache key by hashing the SQL text, parameters, and connection string; on a cache hit, the stored result set is replayed through a custom DbDataReader implementation so EF Core never touches the database; on a miss, the query executes normally and the result is serialized into a row/column format for storage. Cache invalidation is automatic — when SaveChanges/SaveChangesAsync runs, the interceptor parses the SQL to identify affected tables and evicts all cache entries that depend on them. The architecture is a clean provider pattern. The core package (EFCoreSecondLevelCacheInterceptor) defines the interceptor, cache-key generation, SQL table extraction, and the IEFCacheServiceProvider abstraction, while separate companion packages implement backends: MemoryCache, StackExchange.Redis (with custom MessagePack serialization), FusionCache, .NET HybridCache, EasyCaching.Core, and CacheManager.Core. Public entry points are the AddEFSecondLevelCache() DI extension and the Cacheable()/NotCacheable() query extensions, with fluent configuration for expiration modes (absolute/sliding/never), per-query or global policies, and lock modes for concurrency. The codebase is actively maintained (last commit 2026-09-19, zero open issues, dependabot-clean), multi-targets .NET from net462/netstandard2.0 through net10.0, and enforces strict quality gates: TreatWarningsAsErrors, SonarAnalyzer, Meziantou analyzers, and heap-allocation analyzers. Test coverage is extensive — unit tests for key generation, SQL parsing, and data-reader reconstruction, plus integration tests across providers and issue-specific repro projects. Notable craftsmanship includes a hand-written XxHash64 unsafe implementation for fast key hashing, a DbDataReader reconstruction layer that transparently replays cached rows to EF Core, and a SQL table-name extraction processor driving invalidation. Primary risks are the heavy conditional compilation across 10+ target frameworks, SQL parsing heuristics that can miss edge cases (CTEs, subqueries, quoted identifiers), and reliance on third-party cache libraries — CacheManager.Core is explicitly unmaintained upstream. Bulk operations (ExecuteUpdate/ExecuteDelete) bypass the interceptor and require manual invalidation.
The LLM identified 5 files worth highlighting for reuse:
Reconstructs a live ADO.NET DbDataReader from cached EFTableRows, allowing cached query results to be replayed transparently to EF Core without a database round-trip. Implements the full DbDataReader contract (schema, GetValue, GetFieldValue<T>, type coercion for nullable/DateOnly/TimeOnly/JsonElement). Isolated and reusable — the same technique applies to any scenario needing to replay tabular results from a serialized store.
A hand-rolled, allocation-conscious XxHash64 implementation using unsafe pointers for speed, with a managed fallback for older .NET targets. Used to hash SQL text, parameters, and connection strings into compact cache keys. Self-contained and directly extractable into any .NET project needing fast non-cryptographic hashing.
Extracts table names from raw SQL commands and classifies commands (SELECT/INSERT/UPDATE/DELETE) to drive automatic cache invalidation. Combines SQL text heuristics with EF Core metadata reflection to resolve table names across providers (SQL Server, PostgreSQL, MySQL, SQLite). Well-tested against edge cases like bracketed/dotted/backtick-quoted identifiers. Demonstrates non-obvious skill in robust SQL parsing without a full parser.
Loads a live DbDataReader into an EFTableRows structure (column metadata + typed row values) suitable for serialization into any cache backend. Handles schema extraction, null values, and provider-specific type quirks. Reusable as a general-purpose DbDataReader-to-serializable-rows converter.
A custom MessagePack formatter that correctly serializes/deserializes DBNull.Value, which standard MessagePack resolvers mishandle. Solves a recurring data problem when caching ADO.NET results — a small, isolated, and directly reusable component for any MessagePack-based caching layer.