Bknd删除实体Skill bknd-delete-entity

这个技能用于从Bknd平台安全删除实体(表),包括处理依赖关系、数据备份、同步数据库等操作。适用于后端开发和低代码开发,确保数据库管理和应用稳定性。关键词:Bknd、删除实体、数据库管理、依赖处理、数据备份、低代码开发、后端操作、同步工作流。

低代码开发 0 次安装 0 次浏览 更新于 3/8/2026

名称: bknd-delete-entity 描述: 当从Bknd中移除实体时使用。覆盖安全删除实体、处理关系与依赖、数据备份、带–drop标志的同步工作流以及清理孤立数据。

删除实体

安全地从Bknd中移除实体(表),处理依赖关系并避免数据丢失。

先决条件

  • 已存在具有实体的Bknd应用(参见bknd-create-entity
  • 对于代码模式:需访问bknd.config.ts
  • 关键: 删除前备份数据库

警告:破坏性操作

删除实体:

  • 永久移除表及其所有数据
  • 移除所有涉及此实体的关系
  • 可能破坏引用此实体的应用程序代码
  • 无法撤销,除非数据库恢复

何时使用UI vs 代码模式

使用UI模式当

  • 快速原型清理
  • 开发/测试环境
  • 探索存在的依赖关系

使用代码模式当

  • 生产环境更改
  • 需要版本控制
  • 团队协作
  • 可复现的部署

删除前检查清单

在删除实体之前,验证:

1. 检查关系

实体可能通过以下方式被其他实体引用:

  • 外键(多对一)
  • 联结表(多对多)
  • 自引用

2. 检查数据

const api = app.getApi();
const count = await api.data.count("要删除的实体");
console.log(`要删除的记录数: ${count.data.count}`);

3. 检查代码引用

在代码库中搜索:

  • 查询中的实体名称:"实体名称"
  • 类型引用:DB["实体名称"]
  • API调用:api.data.*("实体名称")

4. 备份数据(如需)

// 删除前导出数据
const api = app.getApi();
const allRecords = await api.data.readMany("要删除的实体", {
  limit: 100000,
});

// 保存到文件
import { writeFileSync } from "fs";
writeFileSync(
  "备份-要删除的实体.json",
  JSON.stringify(allRecords.data, null, 2)
);

代码方法

步骤1:识别依赖关系

检查模式中的关系:

// 查找涉及此实体的关系
const schema = em(
  {
    users: entity("users", { email: text().required() }),
    posts: entity("posts", { title: text().required() }),
    comments: entity("comments", { body: text() }),
  },
  ({ relation }, { users, posts, comments }) => {
    // posts 依赖于 users(外键)
    relation(posts).manyToOne(users);
    // comments 依赖于 posts(外键)
    relation(comments).manyToOne(posts);
  }
);

依赖顺序重要: 先删除子实体,后删除父实体。

步骤2:先移除关系

如果实体是关系的目标,更新模式以移除它们:

// 之前:posts 引用 users
const schema = em(
  {
    users: entity("users", { email: text().required() }),
    posts: entity("posts", { title: text().required() }),
  },
  ({ relation }, { users, posts }) => {
    relation(posts).manyToOne(users);
  }
);

// 之后:在删除 users 前移除关系
const schema = em({
  users: entity("users", { email: text().required() }),
  posts: entity("posts", { title: text().required() }),
});

步骤3:从模式中移除实体

简单地从您的bknd.config.ts中移除实体定义:

// 之前
const schema = em({
  users: entity("users", { email: text().required() }),
  posts: entity("posts", { title: text().required() }),
  deprecated_entity: entity("deprecated_entity", { data: text() }),
});

// 之后 - 实体已移除
const schema = em({
  users: entity("users", { email: text().required() }),
  posts: entity("posts", { title: text().required() }),
});

步骤4:预览更改

# 查看将删除的内容(干运行)
npx bknd sync

输出显示:

要删除的表: deprecated_entity
受影响的列: (其他表上无)

步骤5:应用删除

# 使用 drop 标志应用(破坏性)
npx bknd sync --drop

或使用 force(启用所有破坏性操作):

npx bknd sync --force

步骤6:清理代码

移除所有引用:

  • 删除类型定义
  • 移除 API 调用
  • 更新导入

UI方法

步骤1:打开管理面板

导航到http://localhost:1337(或您配置的URL)。

步骤2:转到数据部分

点击侧边栏中的Data

步骤3:选择实体

点击您要删除的实体。

步骤4:检查依赖关系

查找:

  • Relations 选项卡/部分显示连接的实体
  • 关于依赖关系的警告消息

步骤5:导出数据(可选)

如果您需要数据:

  1. 转到实体的数据视图
  2. 导出或手动复制记录
  3. 外部保存备份

步骤6:删除实体

  1. 打开实体设置(齿轮图标或设置选项卡)
  2. 查找Delete EntityRemove按钮
  3. 确认删除
  4. 实体和所有数据被移除

步骤7:同步数据库

删除后,确保数据库同步:

  • 如果提示,点击Sync Database
  • 或从CLI运行npx bknd sync --drop

处理依赖关系

场景:实体具有子记录

问题: 删除users时,postsusers_id外键。

解决方案1:先删除子实体

// 1. 删除所有引用 users 的 posts
const api = app.getApi();
await api.data.deleteMany("posts", {});

// 2. 然后删除 users
//(通过模式移除 + 同步)

解决方案2:先移除关系

// 1. 从模式中移除关系
// 2. 同步以移除外键
// 3. 从模式中移除实体
// 4. 再次使用 --drop 同步

场景:实体是联结表目标

问题: tagsposts_tags联结表中使用。

解决方案:

// 1. 移除多对多关系
const schema = em(
  {
    posts: entity("posts", { title: text() }),
    tags: entity("tags", { name: text() }),
  }
  // 移除:({ relation }, { posts, tags }) => { relation(posts).manyToMany(tags); }
);

// 2. 同步以删除联结表
// npx bknd sync --drop

// 3. 移除 tags 实体
const schema = em({
  posts: entity("posts", { title: text() }),
});

// 4. 再次同步以删除 tags 表
// npx bknd sync --drop

场景:自引用实体

问题: categories引用自身(父/子)。

解决方案:

// 1. 移除自引用关系
const schema = em({
  categories: entity("categories", { name: text() }),
  // 移除自引用关系定义
});

// 2. 同步以移除外键
// npx bknd sync --drop

// 3. 移除实体
//(然后再次同步)

删除多个实体

顺序重要。按依赖顺序删除(先子后父):

// 依赖树:
// users <- posts <- comments
//       <- likes

// 删除顺序:
// 1. comments(依赖于 posts)
// 2. likes(依赖于 posts)
// 3. posts(依赖于 users)
// 4. users(无依赖)

批量删除脚本

// scripts/cleanup-entities.ts
import { App } from "bknd";

async function cleanup() {
  const app = new App({
    connection: { url: process.env.DB_URL! },
  });
  await app.build();
  const api = app.getApi();

  // 按顺序删除
  const entitiesToDelete = ["comments", "likes", "posts"];

  for (const entity of entitiesToDelete) {
    const count = await api.data.count(entity);
    console.log(`从 ${entity} 删除 ${count.data.count} 条记录...`);
    await api.data.deleteMany(entity, {});
    console.log(`已删除所有来自 ${entity} 的记录`);
  }

  console.log("数据清理完成。现在从模式中移除并同步。");
}

cleanup().catch(console.error);

常见陷阱

外键约束错误

错误: Cannot drop table: foreign key constraint

原因: 另一个实体引用了此实体。

修复: 先移除关系,同步,然后移除实体。

联结表未删除

问题: 移除多对多关系后,联结表仍存在。

修复: 运行npx bknd sync --drop以包括破坏性操作。

实体仍显示在UI中

问题: 从代码中删除,但仍在管理面板中显示。

修复:

  • 确保您运行了npx bknd sync --drop
  • 重启Bknd服务器
  • 清除浏览器缓存

应用程序在删除后崩溃

问题: 代码仍引用已删除的实体。

修复:

  • 搜索代码库:grep -r "实体名称" src/
  • 移除所有API调用、类型、导入
  • 修复TypeScript错误

意外删除错误实体

问题: 删除了生产数据。

修复:

  • 如果有备份:从备份恢复
  • 如果无备份:数据永久丢失
  • 预防:删除前始终备份

验证

删除后

# 1. 检查模式导出(实体应不存在)
npx bknd schema --pretty | grep 实体名称

# 2. 验证同步状态
npx bknd sync
# 应显示无待处理更改

通过代码

const api = app.getApi();

// 对于已删除的实体,这应该失败/返回错误
try {
  await api.data.readMany("已删除的实体", { limit: 1 });
  console.log("错误:实体仍存在!");
} catch (e) {
  console.log("确认:实体已成功删除");
}

通过REST API

# 应返回404或错误
curl http://localhost:1337/api/data/已删除的实体

该做与不该做

该做:

  • 删除前备份数据
  • 先检查依赖关系
  • 先删除子实体,后删除父实体
  • 使用npx bknd sync预览后再用--drop
  • 删除后移除代码引用
  • 生产前在开发环境中测试

不该做:

  • 删除具有活动外键的实体
  • 不预览更改就使用--drop
  • 生产环境无备份删除
  • 假设UI删除处理所有清理
  • 忘记移除TypeScript类型/代码引用

相关技能

  • bknd-create-entity - 创建新实体
  • bknd-modify-schema - 修改现有模式
  • bknd-define-relationship - 理解关系依赖
  • bknd-crud-delete - 删除个别记录(非表)
  • bknd-seed-data - 从备份恢复数据