在工控领域,经常遇到断电关机数据库文件损坏的情况,SQLite如此,LiteDb也是这样。ZTO有数万自动化扫描设备,每天都有数百台设备因断电数据库损坏等原因,而不得不重装软件。因此,设计了CsvDb,用于本地保存少量数据,一般只有几百几千行,极限不超过十万行。
Nuget包:NewLife.Core
源码地址:https://github.com/NewLifeX/X/blob/master/NewLife.Core/IO/CsvDb.cs
插入数据
Add插入一个对象(一行数据)到末尾。
var db = new CsvDb<GeoArea>((x, y) => x.Code == y.Code)
{FileName = "data/db.csv"
};
var model = new GeoArea
{Code = Rand.Next(),Name = Rand.NextString(14),
};
db.Add(model);// 把文件读出来
var lines = File.ReadAllLines(db.FileName.GetFullPath());
Assert.Equal(2, lines.Length);
实例化CsvDb时,需要指定模型类,它决定数据格式。构造函数中还可以指定比较器,可以理解为主键字段,用于查找目标数据行。
跑起来效果是这样:
查找数据
Find 用于查找一个对象,本质上引擎内部会遍历所有数据行,逐行对比主键。
var db = new CsvDb<GeoArea>((x, y) => x.Code == y.Code)
{FileName = "data/db.csv"
};
var model = db.Find(new GeoArea { Code = 1234 });
此外,还可以使用 FindAll 查找多行满足条件的数据,指定委托。
public IList<T> FindAll();
IList<T> FindAll(Func<T, Boolean> predicate, Int32 count = -1);
Int32 FindCount();
更新数据
Update 用于更新一个对象,本质上读取所有数据进入内存,修改对应数据后再写回去,成本较高,在数据量不大(小于1万)时问题不大。
var db = new CsvDb<GeoArea>((x, y) => x.Code == y.Code)
{FileName = "data/db.csv"
};
var model = new GeoArea
{Code = 1234,Name = "Stone",
};
db.Update(model);
删除数据
Remove 用于删除满足条件的对象,本质上读取所有数据进入内存,删除满足条件的对象后写回去,成本较高。如果删除后没有剩余数据行,则直接删除文件。
Int32 Remove(T model);
Int32 Remove(IEnumerable<T> models);
Int32 Remove(Func<T, Boolean> predicate);
总结
数万工控设备多年实践表明,Csv数据库很靠谱!
在断电关机的时候,csv文件同样也会损坏,只不过是CsvDb读取时跳过无法解析的错误行,避免了应用崩溃。