前言
上一篇跑通了第一个查询。本篇把增、删、改、查四种操作全部实现,并封装成一个可复用的 PlayerDao 类。学完这篇,你就拥有了一个生产级的数据访问层模板,后续所有表都可以照着这个模式复制。
一、实体类定义
先定义与数据库表对应的C#实体:
1 | // Assets/Scripts/Models/PlayerEntity.cs |
💡 实体类用纯字段而非属性,方便后续序列化。
[Serializable]让它在Inspector中可见(调试用)。
二、数据库管理器单例
所有DAO共享同一个连接字符串和连接池配置:
1 | // Assets/Scripts/Data/DatabaseManager.cs |
三、PlayerDao 完整实现
3.1 CREATE — 新增玩家
1 | // Assets/Scripts/Data/PlayerDao.cs |
⚠️ 密码永远不要明文存储! 这里用BCrypt哈希。实际项目中密码应由服务端处理,客户端不接触明文密码。
3.2 READ — 查询单个 + 查询列表
1 | /// <summary>根据ID查询玩家</summary> |
3.3 UPDATE — 更新玩家信息
1 | /// <summary>更新玩家基础信息,返回影响行数</summary> |
3.4 DELETE — 删除玩家
1 | /// <summary>逻辑删除(推荐):将status设为3</summary> |
💡 生产环境优先用逻辑删除。物理删除会导致外键级联、审计丢失、误操作不可恢复。
四、在Unity中调用
1 | // Assets/Scripts/UI/PlayerPanel.cs |
五、CRUD安全Checklist
| 检查项 | 说明 |
|---|---|
| ✅ 全部使用参数化查询 | 零字符串拼接SQL |
| ✅ 密码BCrypt哈希存储 | 永不明文 |
| ✅ 异步操作不阻塞主线程 | 全部async/await |
| ✅ using管理连接生命周期 | 自动归还连接池 |
| ✅ NULL值用DBNull.Value | 避免NullReferenceException |
| ✅ 逻辑删除优先于物理删除 | 数据安全兜底 |
| ✅ orderBy白名单校验 | 防排序字段注入 |
| ✅ 分页LIMIT/OFFSET参数化 | 防越界查询 |
六、性能优化提示
| 场景 | 优化手段 |
|---|---|
| 批量插入100+条 | 使用事务包裹 + MySqlBulkCopy |
| 高频读取同一数据 | 加内存缓存(Dictionary + TTL) |
| 大表分页慢 | 改用游标分页(WHERE id > @lastId)替代OFFSET |
| 统计查询慢 | 加覆盖索引或预计算汇总表 |
| 并发写入冲突 | 乐观锁(version字段)或悲观锁(SELECT FOR UPDATE) |
总结
本篇实现了完整的CRUD四件套:Insert返回自增ID、GetById+分页列表、Update影响行数、SoftDelete逻辑删除。核心原则只有两个:参数化查询保安全、async/await保流畅。把这个模板吃透,换任何表都能快速复刻。
下一篇我们跳出客户端直连,搭建HTTP API中间层,这才是生产环境的正确姿势。
说些什么吧!