A 200 OK doesn't tell you how much database work happened behind the response.
An endpoint can return the exact same JSON, pass all its integration tests, and still quietly go from 1 database query to 51.
That's the regression I wanted to catch.
QueryGuard.NET
I built QueryGuard.NET to make EF Core query behavior part of the test contract.
It records EF Core commands executed inside a request or test, groups repeated SQL into fingerprints, and lets you enforce query budgets.
await using var scope = QueryGuardScope.Start(
"GET /api/companies",
QueryGuardPolicy.Create("companies")
.WithMaxOccurrencesPerFingerprint(5));
await client.GetAsync("/api/companies");
QueryGuardAssert.Passes(
await scope.CompleteAsync());
In the sample project:
51 queries
same fingerprint executed 50x
Budget: 5
Result: FAIL
After fixing the query:
51 queries -> 1 query
Same response. Different database behavior.
QueryGuard deliberately reports repeated-query candidates, not "N+1 detected", because repeated SQL is evidence of an N+1 pattern, not proof.
Parameter values aren't captured by default, and the current preview only observes EF Core.
SQLite and PostgreSQL are integration-tested in CI.
Try it
https://github.com/Benziza/queryguard-dotnet
The project is MIT licensed and currently available as 0.1.0-preview.1.
One design question I'm especially interested in:
Would you rather enforce a total query count, or a per-fingerprint budget like “this query pattern may execute at most 5 times”?
Feedback from real EF Core codebases would be very useful.
Top comments (0)