EF Core Monitoring
The Storage tab on a service detail page has three subsections: Document Stores (Marten), Event Stores (Marten), and DbContexts (EF Core). This page is for operators triaging "why isn't my DbContext showing up" or "why does the badge say Plain when I'm sure I'm using Wolverine."
For a tour of the badges themselves, see Services → DbContexts.
What you see in the UI
When a monitored service starts up, every EF Core DbContext registered in its container is reported to CritterWatch as a snapshot. The snapshot is taken once per version rollout — the same cadence as the Document Stores and Event Stores cards. If you redeploy with a model change, the new model's entities appear as soon as the new version checks in.
Each card shows:
- The
DbContexttype and the EF Core provider. - The database topology: server, database name, schema. Connection strings are never sent. For multi-tenant contexts, the per-tenant list shows server + database + tenant id only.
- Per-entity details: table name, primary key, indexes, foreign keys, plus chips for sagas, owned types, and view-mapped entities.
- The Wolverine integration shape — the badges across the top of the card.
Why a context might be missing
If a context isn't showing up, one of these is true:
- The service isn't on a recent enough
Wolverine.CritterWatchbuild. EF Core discovery is a recent addition; older builds don't ship the descriptor. Rebuild the service against the current package. UseEntityFrameworkCoreTransactionswas never called. PlainAddDbContext<>()registrations are picked up by an implicit-discovery hook inside that call. NoUseEntityFrameworkCoreTransactions, no implicit discovery.- The
DbContextwas registered after the discovery hook ran. The hook walks the service collection at the point it's called; later registrations aren't picked up. Move the EF Core registration before the Wolverine integration call.
Why a context shows the "Plain" badge
The Wolverine badge on a card is green when the model has been mapped through MapWolverineEnvelopeStorage. When it's grey ("Plain"), Wolverine isn't driving that context's transaction at all — any messaging happens on a separate connection.
Most common cause: the application uses AddDbContext<>() for read-only or non-Wolverine workloads, and got picked up by implicit discovery. The card is correct — the context is there, but it's not part of the transactional outbox path.
If you intended this context to participate in the outbox, switch to AddDbContextWithWolverineIntegration<T>() (or one of the multi-tenant variants).
Pending migrations
The Check pending migrations action on each card runs an on-demand round-trip:
- The console asks the monitored service for its pending migrations on this context.
- The service opens a fresh request scope, builds the
DbContext, and reads__EFMigrationsHistory. - The result comes back and lands on the card — migration names, completion timestamp, optional error.
The probe is on-demand because it opens a synchronous database connection per click. We don't bake it into the regular capabilities snapshot — it's there for triage during a deploy.
If the probe fails, inline error text shows the reason: transient connection failure, missing permissions, or a provider that doesn't support migrations.
What this page deliberately doesn't show
The DbContexts surface captures configuration shape, not runtime state:
- No live
ChangeTrackerentries. Use a profiler. - No query log. EF Core's logging or OpenTelemetry covers this.
- No migration runner. Pending migrations are read-only here; applying them is a deploy concern.
- No raw connection strings. Server, database, and tenant id are the most a card surfaces.
- No per-entity DDL. EF Core's migration scripts live in your application's repo. To see the actual DDL, run
dotnet ef migrations scriptagainst your application.
Cross-references
- Sagas tab. When a context owns Wolverine sagas, the card surfaces a chip per saga type linking to the Sagas tab — the saga's workflow + per-instance OTel replay live there.
- Handler chain detail page. When a per-handler
[Transactional]override is in effect on a chain, that chain's detail page shows a green Transactional badge in its header. That's an independent surface from the DbContext-level transaction-mode badge.
