C# 上位机实战:用 LiteDB 构建本地测试数据管理系统

C# 上位机实战:用 LiteDB 构建本地测试数据管理系统

在上位机和桌面软件开发中,本地数据存储是必不可少的一环。

测试数据、原始采样、运行日志、配置状态......这些信息都需要可靠保存,同时又要方便读取、查询和归档。

很多开发者习惯用 SQLite,但在 C# 上位机项目中,我发现 LiteDB 更符合面向对象、单机轻量存储的需求。

本文带你一步步用 LiteDB 构建一个完整的 测试数据管理系统,从自动生成测试数据,到存储、查询、导出 Excel,再到批量删除和归档。


1. LiteDB 简介

LiteDB 是一个 纯 .NET 实现的嵌入式 NoSQL 数据库

  • 单文件 .db 存储数据,无需数据库服务
  • 面向对象,可直接存储 C# 类对象
  • 支持事务、索引、LINQ 查询
  • 部署简单,非常适合上位机和桌面软件

它更像一个 可安全持久化的对象集合,而不是传统关系型数据库。


2. 项目目标

  1. 自动生成测试数据
  2. 存入 LiteDB
  3. 支持条件查询
  4. 导出 Excel
  5. 批量删除与归档

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:自动生成唯一 ID
  • TestItems:可灵活增减测试项
  • 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 是一个值得尝试的工具。

相关推荐
a努力。11 小时前
京东Java面试被问:双亲委派模型被破坏的场景和原理
java·开发语言·后端·python·面试·linq
冰暮流星11 小时前
javascript赋值运算符
开发语言·javascript·ecmascript
谢娘蓝桥11 小时前
adi sharc c/C++ 语言指令优化
开发语言·c++
刘975311 小时前
【第25天】25c#今日小结
java·开发语言·c#
豆沙沙包?11 小时前
2026年--Lc330-394. 字符串解码(栈)--java版
java·开发语言
2501_9418008811 小时前
从微服务限流到系统稳定性的互联网工程语法实践与多语言探索
开发语言·python
清水白石00811 小时前
《深度剖析 Pandas GroupBy:底层实现机制与性能瓶颈全景解析》
开发语言·python·numpy
2501_9418752811 小时前
从资源隔离到多租户安全的互联网工程语法构建与多语言实践分享
java·开发语言
hui函数11 小时前
python全栈入门到实战【基础篇 03】入门实操:第一个Python程序 + PyCharm使用 + 输入输出全解析
开发语言·python·pycharm
EveryPossible11 小时前
地图展示练习-C
开发语言