Notification Entity Relationships
Summary
No relationship is declared anywhere in the Notification model. There is no HasOne, HasMany, WithOne or WithMany call, no navigation property on any entity, and the migration creates no foreign-key constraint. All seven tables are structurally independent.
Audience
Engineers, architects, QA, support and security reviewers.
Reference Content
The verified reference material for this topic is set out in the sections below.
Logical associations
Four identifier columns imply an association that the database does not enforce.
| Column | Points at | Nullable | Enforced |
|---|---|---|---|
NotificationMessages.RecipientId | recipients | No | No |
NotificationMessages.TemplateId | templates | Yes | No |
NotificationDeliveryAttempts.NotificationMessageId | messages | No | No |
NotificationAuditLog.NotificationMessageId | messages | Yes | No |
NotificationAuditLog.EventId | idempotency ledger | Yes | No |
NotificationMessages.EventId | idempotency ledger | Yes | No |
Preferences associate with recipients by matching tenant, recipient type and external reference rather than by identifier, so there is not even a candidate key column to constrain.
Consequences
No cascade. Nothing propagates a delete. Since no code path deletes anything, this has no current effect, but it means any future cleanup must remove dependents explicitly and in order.
No orphan protection. A message can reference a recipient or template identifier that does not exist. The manual retry path anticipates exactly this: it looks up the recipient and, when none is found, falls back to constructing a delivery target from the address stored on the message itself.
No referential validation on insert. Nothing checks that a referenced row exists before writing.
No eager loading. With no navigation properties, Include cannot be used. Every multi-table read is either a separate query or a manual join, which is what the attempts endpoint does — it queries attempts by message identifier without confirming the message exists, and therefore returns an empty array rather than a not-found result for an unknown identifier.
Denormalisation compensates. The model stores TemplateKey and TemplateVersion alongside TemplateId on the message, and stores the resolved address on the message, so the essential context survives without a join.
Verified absence
No junction table, no self-reference, no inheritance hierarchy, no owned type and no table splitting exists in the model.
Classification
Foundation — the associations exist logically; nothing enforces them.
Requires confirmation
Whether foreign-key constraints are intended before the schema carries production volume requires confirmation.
Related Articles
See Also
Keywords
- Notification database
- Relationships
- Draft database documentation
Source References
microservices/src/notification-service/Infrastructure/NotificationDbContext.csmicroservices/src/notification-service/Domain/NotificationEntities.csmicroservices/src/notification-service/Infrastructure/Migrations/20260705113059_InitialNotificationSchema.csmicroservices/src/notification-service/Infrastructure/Migrations/NotificationDbContextModelSnapshot.csmicroservices/src/notification-service/Application/NotificationDispatcher.cs
Revision Information
- Status: Draft
- Last reviewed: 2026-07-21
- Review cycle: Quarterly