# 模式创建与实体管理器

模型声明即 schema：`sqlClient.createSchema()` 从实体管理器汇总的模型**直接产出建表/删表 DDL**。本页在沙盒里真实演示：**你编写的 `models/` 文件 → EntityManager → DDL**。

## 工作机制

`SqlClient` 的模型由 `EntityManager` 提供——两种用法：

```ts
// 方式一：从目录加载编译后的模型模块（你自己的项目）
const em = EntityManager.of(__dirname, ['./dist/models/book.model.js'])

// 方式二：直接组合内存模型（脚本/测试场景）
const em = EntityManager.combine(Book, BookStore)

const client = newSqlClient(driver, { entityManager: em })
```

`entities()` 会收集模型及其**关联目标**（`Book.store` 会把 `BookStore` 也带上）。

## 沙盒演示：看你的模型生成 DDL

沙盒运行在浏览器里（无文件系统），对应官方**方式二**：在 `main.ts` 里把模型
`import` 进来，经平台提供的 `schemaClient(...)` 组合进 entityManager —— 其余接线
（本地 PGlite 驱动）由平台代劳，与官方 `newSqlClient(driver, { entityManager: em })`
语义一致。

**第一步**：把模型写在工作区 `models/book.model.ts`（进入本页时已默认带好，可直接编辑）：

```ts
// models/book.model.ts —— 会被自动收进 EntityManager
import { model, prop } from '@ts-grm/core'

export const BookStore = model("BookStore", "id", class {
    id = prop.i64()
    name = prop.str(100)
})

export const Book = model("Book", "id", class {
    id = prop.i64()
    name = prop.str(50)
    edition = prop.i32()
    price = prop.num(10, 2)
    store = prop.m2o(BookStore).nullable()
})
```

**第二步**：替换 `main.ts` 为下面脚本并运行：

```ts workspace
// ① 模型来自工作区 models/book.model.ts（用户可编辑文件）
import { Book, BookStore } from './models/book.model'
import { schemaClient } from './infra/sql-client'

// ② createSchema() 要求 sqlClient 带 entityManager：把内存模型显式组合进去
//    （官方「方式二」EntityManager.combine —— 沙盒无文件系统，用内存模型）
const sqlClient = schemaClient(Book, BookStore)

// ③ createSchema()：生成建表/删表脚本（不执行）
const schema = await sqlClient.createSchema()

console.log('=== 建表 DDL ===')
console.log(schema.creationSqlArray.join('\n\n'))

console.log('\n=== 删表 DDL（逆序） ===')
console.log(schema.deletionSqlArray.join('\n'))
```

运行后结果面板会打印完整 DDL——主键、外键（`references ... on delete cascade`）、**多态 check 约束**（如果模型有继承）、唯一约束（`ctx.unique(...)`）都在里面，与上游测试结果一致。

也可以删掉 `models/book.model.ts` 里的模型再运行，看 DDL 如何跟着模型变化——这正是"声明即 schema"。

## 执行边界

- `createSchema()` 只**生成脚本**，不碰数据库；`schema.execute()` 才会真实建表/删表——**示例中不要执行它**，要落库的话在你的项目里用；
- `Schema` 对象可拿 `creationSqlArray / deletionSqlArray / toString()`，方便把 DDL 归档进迁移文件。

## 下一步

SQL 后端七页收束：驱动 → 命名 → 事务 → 方言 → 日志 → 模式创建 → 拦截器。后面的[「API 参考」](../reference/core)提供速查。
