C# 上位机实战:用 LiteDB 构建本地测试数据管理系统
在上位机和桌面软件开发中,本地数据存储是必不可少的一环。
测试数据、原始采样、运行日志、配置状态......这些信息都需要可靠保存,同时又要方便读取、查询和归档。
很多开发者习惯用 SQLite,但在 C# 上位机项目中,我发现 LiteDB 更符合面向对象、单机轻量存储的需求。
本文带你一步步用 LiteDB 构建一个完整的 测试数据管理系统,从自动生成测试数据,到存储、查询、导出 Excel,再到批量删除和归档。
1. LiteDB 简介
LiteDB 是一个 纯 .NET 实现的嵌入式 NoSQL 数据库:
- 单文件
.db存储数据,无需数据库服务 - 面向对象,可直接存储 C# 类对象
- 支持事务、索引、LINQ 查询
- 部署简单,非常适合上位机和桌面软件
它更像一个 可安全持久化的对象集合,而不是传统关系型数据库。
2. 项目目标
- 自动生成测试数据
- 存入 LiteDB
- 支持条件查询
- 导出 Excel
- 批量删除与归档
3. 数据模型设计
csharp
using LiteDB;
using System;
using System.Collections.Generic;
public class TestRecord
{
public ObjectId Id { get; set; }
public DateTime TestTime { get; set; }
public string LotId { get; set; }
public string DeviceId { get; set; }
public bool Pass { get; set; }
public Dictionary<string, double> TestItems { get; set; }
public byte[] RawData { get; set; }
}
ObjectId:自动生成唯一 IDTestItems:可灵活增减测试项RawData:存储原始采样数据
4. 数据库初始化
csharp
public class DatabaseService
{
private readonly LiteDatabase _db;
public ILiteCollection<TestRecord> Records { get; }
public DatabaseService(string dbPath = "testdata.db")
{
_db = new LiteDatabase(dbPath);
Records = _db.GetCollection<TestRecord>("records");
// 创建索引
Records.EnsureIndex(x => x.LotId);
Records.EnsureIndex(x => x.TestTime);
Records.EnsureIndex(x => x.Pass);
}
}
自动创建数据库和集合,索引优化查询性能。
5. 自动生成测试数据
csharp
public class TestDataGenerator
{
private static Random _rand = new Random();
public static TestRecord Generate(string lotId, string deviceId)
{
return new TestRecord
{
TestTime = DateTime.Now,
LotId = lotId,
DeviceId = deviceId,
Pass = _rand.NextDouble() > 0.1,
TestItems = new Dictionary<string, double>
{
{ "Voltage", Math.Round(_rand.NextDouble() * 5, 2) },
{ "Current", Math.Round(_rand.NextDouble() * 2, 2) },
{ "Resistance", Math.Round(_rand.NextDouble() * 100, 2) }
},
RawData = new byte[100]
};
}
}
模拟上位机测试结果,90% 通过率。
6. 数据写入
csharp
public class TestService
{
private readonly DatabaseService _dbService;
public TestService(DatabaseService dbService)
{
_dbService = dbService;
}
public void InsertTestRecord(TestRecord record)
{
_dbService.Records.Insert(record);
}
public void InsertTestBatch(IEnumerable<TestRecord> records)
{
_dbService.Records.InsertBulk(records);
}
}
7. 查询数据
csharp
public class QueryService
{
private readonly DatabaseService _dbService;
public QueryService(DatabaseService dbService)
{
_dbService = dbService;
}
public List<TestRecord> QueryByLot(string lotId)
=> _dbService.Records.Find(x => x.LotId == lotId).ToList();
public List<TestRecord> QueryFailed()
=> _dbService.Records.Find(x => !x.Pass)
.OrderByDescending(x => x.TestTime)
.ToList();
public List<TestRecord> QueryByDateRange(DateTime start, DateTime end)
=> _dbService.Records.Find(x => x.TestTime >= start && x.TestTime <= end).ToList();
}
8. 导出 Excel(ClosedXML)
csharp
using ClosedXML.Excel;
using System.IO;
public class ExcelExporter
{
public static void Export(List<TestRecord> records, string filePath)
{
using var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("TestData");
ws.Cell(1, 1).Value = "Id";
ws.Cell(1, 2).Value = "TestTime";
ws.Cell(1, 3).Value = "LotId";
ws.Cell(1, 4).Value = "DeviceId";
ws.Cell(1, 5).Value = "Pass";
ws.Cell(1, 6).Value = "TestItems";
int row = 2;
foreach (var r in records)
{
ws.Cell(row, 1).Value = r.Id.ToString();
ws.Cell(row, 2).Value = r.TestTime;
ws.Cell(row, 3).Value = r.LotId;
ws.Cell(row, 4).Value = r.DeviceId;
ws.Cell(row, 5).Value = r.Pass;
ws.Cell(row, 6).Value = string.Join(";", r.TestItems.Select(kv => $"{kv.Key}:{kv.Value}"));
row++;
}
wb.SaveAs(filePath);
}
}
9. 批量删除与归档
csharp
public class DataMaintenance
{
private readonly DatabaseService _dbService;
public DataMaintenance(DatabaseService dbService)
{
_dbService = dbService;
}
public void DeleteByLot(string lotId)
{
_dbService.Records.DeleteMany(x => x.LotId == lotId);
}
public void ArchiveOldData(DateTime beforeDate, string archiveDbPath)
{
var oldRecords = _dbService.Records.Find(x => x.TestTime < beforeDate).ToList();
using var archiveDb = new LiteDatabase(archiveDbPath);
archiveDb.GetCollection<TestRecord>("records").InsertBulk(oldRecords);
_dbService.Records.DeleteMany(x => x.TestTime < beforeDate);
}
}
10. 主程序示例
csharp
class Program
{
static void Main()
{
var dbService = new DatabaseService();
var testService = new TestService(dbService);
var queryService = new QueryService(dbService);
// 生成 10 条测试数据
var batch = Enumerable.Range(1, 10)
.Select(i => TestDataGenerator.Generate("LOT202601", $"DEV{i:000}"))
.ToList();
testService.InsertTestBatch(batch);
// 查询失败记录
var failed = queryService.QueryFailed();
Console.WriteLine($"Failed count: {failed.Count}");
// 导出 Excel
ExcelExporter.Export(batch, "TestData.xlsx");
Console.WriteLine("Export done.");
// 删除某批次数据
var maintenance = new DataMaintenance(dbService);
maintenance.DeleteByLot("LOT202601");
Console.WriteLine("Batch deleted.");
// 归档旧数据
maintenance.ArchiveOldData(DateTime.Now.AddDays(-30), "archive.db");
Console.WriteLine("Archive done.");
}
}
11. 总结
- LiteDB 完全贴合 C# 上位机项目:面向对象、灵活、轻量
- 操作简洁:无需写 SQL,数据结构可灵活扩展
- 完整流程可落地:生成 → 存储 → 查询 → 导出 → 删除/归档
对于本地测试数据管理、日志存储、原始采样数据等场景,LiteDB 是一个值得尝试的工具。