v3.0.5
FlexQuery.NET v3.0.5 Release Notes
Release date: 2026-06-24
Overview
v3.0.5 enables expression caching by default, adds ReflectionCache for centralized property metadata caching, hardens DynamicTypeBuilder with bounded FIFO eviction, fixes an EF Core operator handler cache poisoning bug, and expands regression test coverage across all caching layers.
What's New
1. Expression Caching Enabled by Default
FlexQueryCacheSettings.EnableCache is now true by default (was false). Expression trees for predicates and projections are cached after the first build for each unique query shape. Cache keys are deterministic and cover all query dimensions (filter, sort, select, group-by, aggregates, includes, paging). Bounded at 2000 entries per cache instance with FIFO eviction.
Caching is automatically disabled when ExpressionMappings (custom field→expression mappings) are present.
To disable:
FlexQueryCacheSettings.EnableCache = false;2. EF Core Operator Cache Poisoning Fix
UseEfCoreOperators() now sets a marker in options.Items["__EfCoreOperators"] that is included in the expression cache key. Previously, the OperatorHandlerRegistry global static state was not part of the cache key — identical QueryOptions with different operator handler registrations would share a cached expression, returning wrong SQL. Now EF Core operator mode and default operator mode produce distinct cache keys.
3. ReflectionCache
New FlexQuery.NET.Caching.ReflectionCache centralizes all property metadata lookups across the validation, projection, wildcard expansion, and grouping pipelines. Four cache methods backed by ConcurrentDictionary:
GetProperty(Type, string)— case-insensitive, per (type, name)GetProperties(Type)— per typeTryResolvePropertyChain(Type, string, out chain)— dot-path resolution with collection traversalTryGetCollectionElementType(Type, out elementType)—IEnumerable<T>interface scan
Refactored call sites (14 files): SafePropertyResolver, ProjectionBuilder, DefaultProjectionRule, FieldAccessValidator, AggregateResultBuilder, ProjectionOptimizer, QueryBuilder, FlatProjectionBuilder (6 sites), TypeHelper.
4. DynamicTypeBuilder Cache Hardening
Added bounded FIFO eviction via FlexQueryCacheSettings.MaxCacheSize. Cache key changed from Type.GetHashCode() (unstable) to Type.FullName (stable). Added Clear() and Count API. Added ArgumentNullException guard on null input.
5. Cache Key Correctness Tests
3 new tests in CacheKeyCorrectnessTests:
| Test | Verifies |
|---|---|
CanCache_WithExpressionMappings_ReturnsFalse |
ExpressionMappings disables caching |
CacheKey_IdenticalQuery_DifferentEntityType_DifferentKey |
Entity type is in the cache key |
SortOrder_DifferentFieldOrder_DifferentKey |
Sort order is preserved in the key |
6. New Test Coverage
| Area | Tests | Focus |
|---|---|---|
ReflectionCacheTests |
35 | GetProperty, GetProperties, chain resolution, collection detection, thread safety, cache-miss consistency, path edge cases |
DynamicTypeBuilderTests |
14 | Shape generation, FIFO eviction, thread safety, null guard, cache reuse |
CacheKeyCorrectnessTests |
8 | Filter/select/sort/entity-type differentiation, ExpressionMappings gate |
CacheIsolationTests |
3 | ParserCache deep-clone isolation |
Migration Guide
Expression Caching
No code changes required. Caching is transparent — cache keys are deterministic and the cache is bounded. If memory pressure is a concern:
FlexQueryCacheSettings.EnableCache = false; // Disable globally
// Or per-query:
options.EnableCache = false; // Disable for a single queryReflectionCache
No code changes required. All existing code paths now delegate to ReflectionCache internally. The public API is unchanged.
DynamicTypeBuilder
No code changes required. The cache is now bounded — if you observe cache eviction of projection types, increase FlexQueryCacheSettings.MaxCacheSize (default 2000).
Upgrading
dotnet add package FlexQuery.NET --version 3.0.5
dotnet add package FlexQuery.NET.Adapters.AgGrid --version 3.0.5
dotnet add package FlexQuery.NET.Dapper --version 3.0.5Full test suite: 827 tests passing, zero regressions.