Notification Query Patterns
Summary
Every query is inline LINQ against a DbSet. Read-only paths use no-tracking queries consistently; paths that intend to mutate deliberately do not.
Audience
Engineers, architects, QA, support and DevOps engineers.
Reference Content
The verified reference material for this topic is set out in the sections below.
Tracking discipline
No-tracking is applied on the read paths: the idempotency existence check, template resolution, preference evaluation, the retry path's recipient lookup, and the single-message, attempts, failed-queue, processed-event, audit and template-list reads.
Tracking is intentionally retained where a mutation follows: the read-state lookup, the template update lookup, the recipient upsert lookup, and the retry path's message lookup. The distinction is applied correctly at every site reviewed.
Inbox
A two-step query. First, recipient identifiers are resolved by tenant, external reference and optionally recipient type, projecting only the identifier. When that set is empty the handler returns an empty result without a second query. Otherwise messages are filtered to those identifiers and the in-app channel, optionally excluding rows already read, ordered by creation descending, and limited by a page size clamped to 1–500 with a default of 100.
The identifier set is materialised in memory and then used in a containment predicate, so a recipient with many rows produces a correspondingly large parameter list.
Templates
Resolution runs up to two queries: the tenant-specific row filtered on tenant, key, channel and active, ordered by version descending, taking the first; then, only if that found nothing, the same query with a null tenant. Preferring a tenant override over the global default is therefore a query-ordering behavior, not a database construct.
The list endpoint applies four optional filters and orders by key, then channel, then version descending. Omitted filters are not applied at all, so an unfiltered call spans every tenant.
Preferences
One query loads candidate rows for the tenant, recipient type, external reference and channel, then exact-versus-wildcard event matching is resolved in memory rather than in the database.
Statistics
Eight independent count queries in one handler — see statistics storage.
Audit
Three optional filters — event, correlation and message — applied only when supplied, ordered by occurrence descending, with a page size clamped to 1–1000 and a default of 200. An unfiltered call returns the most recent rows across all tenants and events.
Retry and diagnostics
The retry path loads the message tracked, loads the recipient no-tracking, and falls back to the address stored on the message when no recipient row is found. The attempts query filters by message identifier and orders ascending by attempt number without confirming the message exists.
Failed notifications
Filters messages on the failed status alone, orders by creation descending, clamps the page size to 1–500 with a default of 100. No tenant predicate and no index leading with status.
Paging
Every collection query uses a clamped take with no skip, no continuation token and no total count. Callers cannot detect truncation, and there is no stable cursor for iterating beyond the first page.
Verified absence
No raw SQL, no FromSqlRaw, no ExecuteUpdate, no ExecuteDelete, no stored procedure call, no compiled query, no split query and no explicit AsSplitQuery or Include anywhere in the reviewed source.
Classification
Implemented.
Requires confirmation
Whether cursor paging and tenant predicates on the administrative reads are planned requires confirmation.
Related Articles
See Also
Keywords
- Notification database
- Query Patterns
- Draft database documentation
Source References
microservices/src/notification-service/Api/NotificationEndpoints.csmicroservices/src/notification-service/Application/NotificationDispatcher.csmicroservices/src/notification-service/Application/TemplateEngine.csmicroservices/src/notification-service/Application/PreferenceEvaluator.csmicroservices/src/notification-service/Infrastructure/NotificationDbContext.cs
Revision Information
- Status: Draft
- Last reviewed: 2026-07-21
- Review cycle: Quarterly