pub struct DbContext { /* private fields */ }Expand description
The session / unit-of-work entry point.
Entity sets are lazy-created via ctx.set::<T>(). Metadata is loaded from
the process-level MetadataCache on DbContextOptions (built once per
context_key, then Arc-shared). save_changes() commits all pending
changes in a transaction.
Implementations§
Source§impl DbContext
impl DbContext
Sourcepub fn from_options(options: &DbContextOptions) -> EFResult<Self>
pub fn from_options(options: &DbContextOptions) -> EFResult<Self>
Creates the context from options (uses the provider factory stored in options).
Entity metadata is loaded from the process-level MetadataCache on
DbContextOptions — inventory::iter + IEntityTypeConfiguration::configure()
run once per context_key (first call), then the result is Arc-shared
across all DbContext instances. Per-instance ModelBuilder mutations
(has_query_filter, etc.) after construction only affect this instance.
pub fn set<T>(&mut self) -> &mut DbSet<T>where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
Sourcepub fn model(&mut self) -> &mut ModelBuilder
pub fn model(&mut self) -> &mut ModelBuilder
Returns the model builder for Fluent API configuration.
Sourcepub fn model_builder(&self) -> &ModelBuilder
pub fn model_builder(&self) -> &ModelBuilder
Returns a read-only reference to the model builder.
Sourcepub fn entity_metas_contains<T: IEntityType>(&self) -> bool
pub fn entity_metas_contains<T: IEntityType>(&self) -> bool
Returns true if an entity of type T has been discovered and
registered in the entity metadata map.
Sourcepub fn discover_entities(&mut self) -> EFResult<()>
pub fn discover_entities(&mut self) -> EFResult<()>
No-op since metadata caching was introduced.
Historically, this method iterated inventory::iter to register entity
metadata and apply #[entity(T)] configurations. That work now happens
in MetadataCache::build(), invoked lazily by from_options() via
MetadataCache::get_or_build(). The result is Arc-shared across all
DbContext instances with the same context_key.
Retained as a public method for backward compatibility — existing code
calling ctx.discover_entities()? after from_options() continues to
compile and run (as a no-op). The metadata is already populated.
Sourcepub fn detect_changes(&mut self)
pub fn detect_changes(&mut self)
Detects changes on all tracked DbSets by comparing property snapshots.
Sourcepub async fn ensure_created(&self) -> EFResult<()>
pub async fn ensure_created(&self) -> EFResult<()>
Creates all tables for registered entity types.
Sources metas from model_builder.build(), which applies all Fluent
API configurations and #[entity(T)] overrides. Entities are
discovered automatically via #[derive(EntityType)]; call
discover_entities() first, or use set::<T>() to register manually.
Sourcepub async fn ensure_deleted(&self) -> EFResult<()>
pub async fn ensure_deleted(&self) -> EFResult<()>
Drops all tables for registered entity types.
Source§impl DbContext
impl DbContext
Sourcepub fn provider(&self) -> &dyn IDatabaseProvider
pub fn provider(&self) -> &dyn IDatabaseProvider
Returns the database provider.
Sourcepub fn change_tracker(&self) -> &ChangeTracker
pub fn change_tracker(&self) -> &ChangeTracker
Returns a read-only reference to the change tracker.
Sourcepub fn change_tracker_mut(&mut self) -> &mut ChangeTracker
pub fn change_tracker_mut(&mut self) -> &mut ChangeTracker
Returns a mutable reference to the change tracker.
Sourcepub fn clear_tracking(&mut self)
pub fn clear_tracking(&mut self)
Detaches every tracked entity and clears the change tracker.
Called automatically when a DbContext::transaction closure returns
TxOutcome::Rollback: the database rolled back, so keeping the
entities tracked would let those writes leak into a later
save_changes. Entity instances themselves are not modified — only the
context’s tracking state is dropped.
Sourcepub async fn sql_query<T: IFromRow + IEntityType>(
&self,
sql: &str,
params: &[DbValue],
) -> EFResult<Vec<T>>
pub async fn sql_query<T: IFromRow + IEntityType>( &self, sql: &str, params: &[DbValue], ) -> EFResult<Vec<T>>
Executes a raw SQL query and materializes the result rows into entities.
This is the escape hatch for complex queries (multi-table JOINs, CTEs, window functions) that are hard to express via LINQ. The caller is responsible for SQL correctness and parameterization.
§Example
let blogs: Vec<Blog> = ctx
.sql_query("SELECT * FROM blogs WHERE id = ?", &[DbValue::I32(1)])
.await?;Sourcepub fn transaction_mut(&mut self) -> Option<&mut Box<dyn ITransaction>>
pub fn transaction_mut(&mut self) -> Option<&mut Box<dyn ITransaction>>
Returns a mutable reference to the ambient transaction handle, if one
is active (registered by use_transaction() / transaction()).
Inside a scoped transaction closure, use this to access the ambient
handle for savepoint and isolation operations. A handle returned by
DbContext::begin_transaction is owned by the caller instead, so use
that handle directly. The borrow must be released (by scoping) before
calling save_changes() or other &mut self methods.
Sourcepub async fn begin_transaction(&mut self) -> EFResult<Box<dyn ITransaction>>
pub async fn begin_transaction(&mut self) -> EFResult<Box<dyn ITransaction>>
Begins a transaction and returns a typed handle.
The handle is standalone: it is not registered as the context’s
current transaction. Queries and a later save_changes() do not join
it; save_changes() keeps self-managing its own transaction. Use
DbContext::transaction for a context-scoped transaction where
queries, bulk DML and save_changes() all join.
commit / rollback consume the handle by value, preventing
use-after-commit at the type level.
Sourcepub async fn begin_transaction_with(
&mut self,
isolation: IsolationLevel,
) -> EFResult<Box<dyn ITransaction>>
pub async fn begin_transaction_with( &mut self, isolation: IsolationLevel, ) -> EFResult<Box<dyn ITransaction>>
Like DbContext::begin_transaction, with an isolation level applied
at transaction start.
Sourcepub async fn use_transaction<F, R>(&mut self, f: F) -> EFResult<R>
pub async fn use_transaction<F, R>(&mut self, f: F) -> EFResult<R>
Executes a closure within an ambient transaction.
Registers the transaction as ambient for the duration of f, so every
statement issued through the context — queries, navigation loading,
bulk DML, raw SQL and save_changes() — reuses the same transaction
connection. Commits on Ok, rolls back on Err.
For an abort-with-result exit, use DbContext::transaction instead.
The closure receives &mut DbContext and must return a pinned boxed
future. This signature works around Rust’s async borrow checker by
letting the closure capture ctx by mutable reference while still
producing a Send future.
§Example
ctx.use_transaction(|ctx| Box::pin(async move {
ctx.add::<Blog>(blog);
ctx.save_changes().await?;
Ok(())
})).await?;Sourcepub async fn use_transaction_with<F, R>(
&mut self,
isolation: IsolationLevel,
f: F,
) -> EFResult<R>
pub async fn use_transaction_with<F, R>( &mut self, isolation: IsolationLevel, f: F, ) -> EFResult<R>
Like DbContext::use_transaction, with an explicit isolation level
applied at transaction start.
Sourcepub async fn transaction<F, R>(&mut self, f: F) -> EFResult<R>
pub async fn transaction<F, R>(&mut self, f: F) -> EFResult<R>
Executes a closure within an ambient transaction and lets the closure decide whether to commit or roll back — while still returning a value.
This is the handler-level unit of work: every statement issued through
ctx inside the closure (queries, save_changes, execute_update,
execute_delete, raw SQL) uses the same transaction connection, so
reads observe the handler’s own uncommitted writes.
Ok(TxOutcome::Commit(value))— commit, returnOk(value)Ok(TxOutcome::Rollback(value))— roll back, detach tracked entities, returnOk(value)Err(e)— roll back, detach tracked entities, returnErr(e)
Unlike DbContext::use_transaction, a business rejection does not
have to be encoded as an error.
§Example
let result = ctx.transaction(|ctx| Box::pin(async move {
// Batch update A, then join-query A/B/C — both on the transaction
// connection, so the query sees the uncommitted update.
linq!(ctx.set::<A>(), |a: A| a.flag; set a.flag, true; execute_update).await?;
let rows = linq!(ctx.set::<A>(), |a: A| a.flag).to_list().await?;
if !rows.iter().all(|r| r.ok()) {
return Ok(TxOutcome::Rollback(BizResult::Rejected));
}
Ok(TxOutcome::Commit(BizResult::Done))
})).await?;Sourcepub async fn transaction_with<F, R>(
&mut self,
isolation: IsolationLevel,
f: F,
) -> EFResult<R>
pub async fn transaction_with<F, R>( &mut self, isolation: IsolationLevel, f: F, ) -> EFResult<R>
Like DbContext::transaction, with an explicit isolation level
applied at transaction start.
Source§impl DbContext
impl DbContext
Sourcepub fn add<T>(&mut self, entity: T)where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
pub fn add<T>(&mut self, entity: T)where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
Adds a new entity in Added state. The entity will be INSERTed during
save_changes().
Sourcepub fn attach<T>(&mut self, entity: T)where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
pub fn attach<T>(&mut self, entity: T)where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
Attaches an existing entity in Unchanged state with a snapshot for
future change detection.
Sourcepub fn update<T>(&mut self, entity: T)where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
pub fn update<T>(&mut self, entity: T)where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
Marks an entity as Modified — all fields will be UPDATEd during
save_changes().
Sourcepub fn upsert<T>(&mut self, entity: T)where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
pub fn upsert<T>(&mut self, entity: T)where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
Marks an entity for upsert (INSERT … ON CONFLICT DO UPDATE).
Sourcepub fn remove_at<T>(&mut self, index: usize) -> EFResult<()>where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
pub fn remove_at<T>(&mut self, index: usize) -> EFResult<()>where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
Marks the entity at the given index as Deleted.
Sourcepub fn remove_all<T>(&mut self)where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
pub fn remove_all<T>(&mut self)where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + Send + Sync + 'static,
Marks all entities of type T as Deleted.
Sourcepub async fn load_all<T>(&mut self) -> EFResult<()>where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + ILazyInit + Send + Sync + 'static,
pub async fn load_all<T>(&mut self) -> EFResult<()>where
T: IEntityType + IEntitySnapshot + IGetKeyValues + IFromRow + INavigationSetter + ILazyInit + Send + Sync + 'static,
Loads all rows from the database into the DbSet as Unchanged.
Clears existing entries and tracker state for type T first.
Source§impl DbContext
impl DbContext
Sourcepub async fn save_changes(&mut self) -> EFResult<SaveChangesResult>
pub async fn save_changes(&mut self) -> EFResult<SaveChangesResult>
Saves all pending changes across all DbSets.
Detects changes, runs interceptors, executes INSERT/UPDATE/DELETE in a transaction, and clears tracked entries on success.