DbContext 与 DI 注册

`DbContext` 是工作单元的入口。与传统 ORM 不同,`rust-ef` 的 `DbContext` 使用**类型映射(type-map)**存储 `DbSet`,无需为每个实体定义字段。

手动创建

use rust_ef::db_context::{DbContext, DbContextOptionsBuilder};
use rust_ef_sqlite::DbContextOptionsBuilderExt as _;

let mut builder = DbContextOptionsBuilder::new();
builder.use_sqlite("app.db");
let mut ctx = DbContext::from_options(&builder.build())?;
// from_options() 自动发现所有 #[derive(EntityType)] 标注的实体
// 并应用所有 #[entity(T)] 配置 —— 无需手动调用 discover_entities()

ctx.ensure_created().await?;  // 直接建表,元数据已就绪

DI 注册(推荐)

use rust_dix::*;
use rust_ef::di::*;
use rust_ef::db_context::DbContext;
use rust_ef_sqlite::DbContextOptionsBuilderExt as _;

let provider = ServiceCollection::new()
    .add_dbcontext(|options| {
        options.use_sqlite("data source=app.db");
    })
    .build()
    .unwrap();

// 推荐:owned 解析,直接 &mut self 访问
// rust-dix 0.6+: get_owned() 返回 Result<T, RdiError>
let mut ctx: DbContext = provider.get_owned().unwrap();

// 或:共享解析(Arc<DbContext>,&self 访问,同一 scope 内共享)
// use rust_dix::scope::ScopeFactory;
// let scope = provider.create_scope();
// let ctx: Arc<DbContext> = scope.get().unwrap();

多数据库 Keyed 注册

let provider = ServiceCollection::new()
    .add_dbcontext_keyed("primary", |options| {
        options.use_postgres("host=primary/db");
    })
    .add_dbcontext_keyed("logs", |options| {
        options.use_sqlite("logs.db");
    })
    .build()
    .unwrap();

// Owned 解析(推荐):
let mut primary: DbContext = provider.get_keyed_owned("primary").unwrap();
let mut logs: DbContext = provider.get_keyed_owned("logs").unwrap();

// 共享解析:
// let primary: Arc<DbContext> = scope.get_keyed("primary");

关键点

| 点 | 说明 | |---|------| | `from_options()` 自动发现实体 | 自动调用 `discover_entities()`,无需手动注册元数据 | | `set::<T>()` 是 lazy 的 | 首次调用时创建 DbSet,重复调用返回同一实例 | | `ensure_created()` 可直接调用 | 元数据已在 `from_options()` 中自动就绪 | | Owned 解析(推荐) | `get_owned()` → `DbContext`,`&mut self` 访问,无需锁 | | Shared 解析 | `scope.get()` → `Arc<DbContext>`,`&self` 访问,同一 scope 内共享 |

下一节:[第一个 CRUD 流程](first-crud.md)