Skip to main content

Module db_context

Module db_context 

Source
Expand description

DbContext, DbContextOptions, and ChangeTracker — the session / unit-of-work layer.

§Architecture

DbContext is the concrete context type. Entity sets use a type-map: ctx.set::<Blog>() lazy-creates DbSet<Blog>. SetOps<T> dispatchers enable save_changes() to iterate all entity types.

§Provider Factory

DbContextOptions stores a provider_factory closure injected by the provider extension methods (use_sqlite, use_postgres, use_mysql). DbContext::from_options() calls this factory to create the provider.

§Ownership and Mutation

DbContext methods (set::<T>(), save_changes(), detect_changes()) require &mut self — this is idiomatic Rust, not a limitation. The DI integration (add_dbcontext) registers the context as Scoped and supports two resolution modes:

  • Owned (recommended for handlers): provider.get_owned::<DbContext>() returns a fresh DbContext with direct &mut self access. Handlers declare a bare ctx: DbContext field marked with #[inject(owned)]; #[derive(Inject)] resolves it via get_owned(). Unmarked fields fall back to Default::default().
  • Shared (within a scope): scope.get::<DbContext>() returns Arc<DbContext> for consumers that only need &self access.
// Owned — idiomatic &mut self, no locks:
// rust-dix 0.6+: get_owned() returns Result<T, RdiError>
let mut ctx: DbContext = provider.get_owned()?;
ctx.set::<Blog>().add(blog);
ctx.save_changes().await?;

§Thread Safety

DbContext is not thread-safe — a single instance must not be shared across threads. This is a design decision (aligned with EFCore), not a limitation.

Correct usage: each request / operation owns its own DbContext instance (via get_owned() or a fresh scope):

let mut ctx: DbContext = provider.get_owned()?;
// This instance is exclusively owned — &mut self works directly.

rust-webapp: the HTTP pipeline creates a DI scope per request and resolves handlers via get_owned::<Handler>(). Handlers own a fresh DbContext — no manual scope management needed.

Anti-pattern: sharing via Arc<Mutex<DbContext>> causes tracking pollution — Thread A’s save_changes() would commit Thread B’s pending changes. Prefer owned resolution.

Structs§

DbContext
DbContextOptions
DbContextOptionsBuilder
SaveChangesResult

Functions§

delete_deleted_phase
Phase 3: DELETE Deleted entities.
insert_added_phase
Phase 1a: INSERT Added (non-upsert) entities, then backfill generated PKs.
save_one_set
update_modified_phase
Phase 2: UPDATE Modified entities (partial update via modified_properties).
upsert_added_phase
Phase 1b: UPSERT Added entities (is_upsert = true).