QuerySpec.Analyzers
4.0.0
See the version list below for details.
dotnet add package QuerySpec.Analyzers --version 4.0.0
NuGet\Install-Package QuerySpec.Analyzers -Version 4.0.0
<PackageReference Include="QuerySpec.Analyzers" Version="4.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="QuerySpec.Analyzers" Version="4.0.0" />
<PackageReference Include="QuerySpec.Analyzers"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add QuerySpec.Analyzers --version 4.0.0
#r "nuget: QuerySpec.Analyzers, 4.0.0"
#:package QuerySpec.Analyzers@4.0.0
#addin nuget:?package=QuerySpec.Analyzers&version=4.0.0
#tool nuget:?package=QuerySpec.Analyzers&version=4.0.0
QuerySpec
Build query specifications — filters, sorts, projections — as plain data, then translate them to LINQ against Entity Framework Core. Useful when filter input comes from somewhere other than code: an HTTP request, a saved view, a rules engine, a config file. Instead of writing expression trees by hand (or giving up and interpolating strings), you describe the query as data and let QuerySpec turn it into SQL.
On top of that, the Core package ships the cross-cutting pieces most data-access layers end up reinventing: auditing, data masking and row-level security, caching, resilience (retry / circuit breaker / rate limiting), and monitoring.
Packages
| Package | What it does |
|---|---|
QuerySpec.Core |
Filter/sort specifications and the pluggable auditing, security, caching, resilience, and monitoring layers. No EF dependency. |
QuerySpec.EFCore |
Translates AdvancedFilterExpression into LINQ expression trees for IQueryable<T>. Compiled-expression cache included. |
QuerySpec.DependencyInjection |
AddQuerySpec(...) builder for Microsoft.Extensions.DependencyInjection. Pulls in StackExchange.Redis for distributed caching. |
Targets net8.0, net9.0, net10.0.
Install
dotnet add package QuerySpec.Core
dotnet add package QuerySpec.EFCore
dotnet add package QuerySpec.DependencyInjection
Most apps want all three. Core alone is fine if you're not using EF Core or DI.
Supported frameworks
QuerySpec targets net8.0 (LTS, supported through November 2026), net9.0 (STS, supported through May 2026), and net10.0 (LTS). These are the only supported TFMs. netstandard2.0 is not targeted.
The library relies on APIs that are unavailable on netstandard2.0: System.Threading.Lock, params ReadOnlySpan<T>, TimeProvider, async JsonSerializer overloads, and related BCL surface. Adding a netstandard2.0 target would require either reverting those improvements or shipping a parallel conditional-compilation codebase — a cost that does not make sense for an enterprise data-access library targeting modern .NET.
Consumers on .NET Framework 4.x or older runtimes should use Ardalis.Specification or another netstandard2.0-compatible alternative.
For the .NET support lifecycle see https://dotnet.microsoft.com/platform/support/policy/dotnet-core.
Applying a filter to an EF Core query
using QuerySpec.Core.Filtering;
using QuerySpec.EFCore;
var filter = new AdvancedFilterExpression
{
Field = "Department",
Operator = FilterOperator.Equal,
Value = "Engineering"
};
var users = await QuerySpecExpressionTranslator
.ApplyFilter(dbContext.Users, filter)
.ToListAsync();
AdvancedFilterExpression is plain data — deserialize it from a request body, compose it from query-string parameters, load it from a saved view. The translator turns it into the same expression tree you'd have written yourself, so EF Core generates the same SQL it always would.
For nested logic, use And/Or groups instead of a flat Field/Operator/Value. See the samples/ folder for a worked example.
Wiring up the cross-cutting features
AddQuerySpec is opt-in — you only register what you use:
builder.Services.AddQuerySpec(qs => qs
.WithAuditing(a => a.LogAllQueries())
.WithSecurity(s => s.EnableDataMasking())
.WithCaching(c => c.UseMemoryCache())
.WithResilience(r => r.EnableCircuitBreaker())
);
Each With* call is independent. Skip the ones you don't need.
What's in the box
- 50+ filter operators — comparison, string (contains / starts-with / regex), collection membership, null checks, temporal ranges, geospatial.
- Compiled expression cache — repeated translations of the same specification shape don't re-walk the tree.
- Auditing — per-query log entries with integrity hashing, suitable for compliance reporting.
- Security — column-level masking, field encryption, row-level security predicates, dynamic permission evaluation.
- Caching — in-memory out of the box; Redis via
StackExchange.Rediswhen you pull inQuerySpec.DependencyInjection. - Resilience — retry with backoff, circuit breaker, rate limiting.
- Monitoring — metrics, health checks, OpenTelemetry hooks.
License
MIT — see LICENSE.
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.