LiteDB:实例长期持有vs每次CRUD开闭,更新失效问题咨询
LiteDB更新失败问题分析与解决
我挺喜欢LiteDB,但确实社区支持不足这点很头疼,连论坛或Discord都没有,排查问题全靠自己试。先给你理清两种数据库使用方式的核心注意点,再解决你遇到的更新失败问题:
两种用法的核心原则
- 长期保持数据库实例开启:这是LiteDB推荐的常规用法,它的连接是线程安全的,长期持有不会有性能问题,还能避免反复打开关闭连接的开销。
- 每次CRUD操作开关实例:适合低频率操作的脚本场景,但必须注意:绝对不能持有
using块外的数据库/集合实例,因为using块结束后,数据库资源会被释放,对应的实例会失效。
你的代码问题拆解
你第二段代码更新失败,核心有两个错误:
1. 非法使用已释放的集合实例
你在第二个using块外持有了recalledGames集合实例,当using块结束,内部的db对象被释放,recalledGames的内部状态也会失效。此时调用recalledGames.FindAll()属于非法操作,哪怕侥幸拿到对象,后续流程也会埋下隐患。正确的查询写法应该把查询逻辑放在using块内部:
Game firstGame; using (var db = new LiteDatabase(ConnectionString)) { var recalledGames = db.GetCollection<Game>("games"); firstGame = recalledGames.FindAll().First(); }
2. 更新时使用了错误的集合名
你最后一个using块里写的是db.GetCollection<Game>(),LiteDB默认会把类名Game作为集合名,但你之前插入数据用的是集合名"games"(复数)——相当于你在更新一个完全不同的空集合,自然不会有任何数据变化。必须指定和插入时一致的集合名:
using (var db = new LiteDatabase(ConnectionString)) { var games = db.GetCollection<Game>("games"); games.Update(firstGame); // 注:LiteDB在using块结束时会自动提交变更,手动Commit除非是开启了显式事务,否则可以省略 }
修正后的完整代码
using (var db = new LiteDatabase(ConnectionString)) { var games = db.GetCollection<Poco.Game>("games"); Poco.Game newGame = new Poco.Game() { Id = ObjectId.NewObjectId(), Name = "R-Type" }; games.Insert(newGame); } Game firstGame; using (var db = new LiteDatabase(ConnectionString)) { var recalledGames = db.GetCollection<Game>("games"); firstGame = recalledGames.FindAll().First(); } firstGame.Name = "BC's quest for tyres"; using (var db = new LiteDatabase(ConnectionString)) { var games = db.GetCollection<Game>("games"); games.Update(firstGame); }
补充说明:LiteDB的Update方法确实是根据主键(你的Id字段)匹配数据的,但前提是操作的是同一个集合,且主键值正确。
内容的提问来源于stack exchange,提问作者stigzler
相关产品推荐
相关产品推荐

