
LiteDB 不需要安装服务、不依赖外部进程,只要 NuGet 引入包 + 一个可写文件路径,就能直接读写。 它不是 SQLite 那种关系型数据库,也不是 MongoDB 那种要起服务的 NoSQL;它是纯 C# 实现的单文件文档数据库,适合桌面工具、CLI 应用、IoT 设备等单用户本地场景。高并发、多线程共享、复杂事务都不在它设计范围内——别硬塞。
怎么装包并确保路径可用
用 dotnet add package LiteDB 或 Visual Studio 的 NuGet 界面装最新稳定版(5.x 或 6.x,别用已归档的 4.x)。装完后,关键不是“怎么连”,而是“路径能不能写”:
LiteDatabase 构造函数传入的路径,目录必须存在 —— LiteDB 不会自动创建父目录,比如 "data\users.db" 要求 data 文件夹已存在,否则抛 DirectoryNotFoundException调试时默认工作目录是 binDebuget8.0,不是项目根目录;建议显式拼路径:Path.Combine(AppContext.BaseDirectory, "mydata.db")不要用全局静态 LiteDatabase 实例,尤其在 WinForms/WPF 多线程 UI 场景下,极易触发文件锁冲突
插入数据时 ID 字段为什么总出错
ID 是 LiteDB 最容易翻车的点,核心就一条:它只认 _id 或 Id(大小写敏感),且该属性必须是 public、可读可写、类型匹配查询逻辑:
没定义 Id 或 _id 字段?LiteDB 会自动生成 ObjectId,但你后续用 int 查询(如 Find(x => x.Id == 123))一定查不到写了 public int Id { get; private set; }?不行,private set 会被跳过,序列化后 Id 是 0,查不到也插不进想用 int 主键又不想手动赋值?得配 BsonAutoId.Int32,否则新对象 Id 默认为 0,插入失败(主键重复)推荐写法:public ObjectId Id { get; set; } = ObjectId.NewObjectId();,或明确声明 [BsonId] 特性
查询查不到数据,常见 LINQ 陷阱有哪些
LINQ 表达式看着像 C#,但 LiteDB 只支持子集,很多你以为能用的语法一跑就崩:
x.Name.Contains("a") ✅ 可用;x.Name.Trim().ToLower().Contains("a") ❌ 不支持方法链,抛 NotSupportedExceptionx.Created.Date == DateTime.Today ❌ Date 属性访问不被翻译,要用 x.Created >= todayStart && x.Created Find("Name == ‘Alice’") 这种字符串查询已弃用,且不校验字段名,容易静默失败,别用大数据量时 FindAll() 是全表扫描,没索引的 Where 条件性能随记录数线性下降;高频查询字段记得加索引:collection.EnsureIndex(x => x.Name)
多线程下怎么避免文件锁和数据错乱
LiteDatabase 实例本身 不是线程安全的,官方明确要求:每个线程要么有自己的实例,要么串行访问。实际操作中:
✅ 推荐每次操作都新建 LiteDatabase(开销极小,底层有轻量连接池优化),配合 using 自动释放❌ 绝对不要把 LiteDatabase 声明成 static 全局变量,然后多个线程同时调 Insert 或 Find如果真要复用实例(比如 Web API 中短暂生命周期的请求处理),必须加锁(lock 或 AsyncLock),但通常不如新建来得干净注意:即使同一进程内,多个 LiteDatabase 实例打开同一个 .db 文件,LiteDB 内部会做文件锁协调,但写入并发仍受限 —— 它本就不是为高写入设计的
真正容易被忽略的是:LiteDB 的“轻量”是有代价的 —— 它不提供事务回滚、不支持跨集合关联、不处理网络分区。当你开始琢磨“怎么让两个集合的数据强一致”或者“怎么给用户导出带事务的日志”,就该停下来想想,是不是已经超出了它的能力边界。

评论(0)